dllmain/dllmaincrtstartup在dll中不执行



dll构建中的初始化代码在导入时不会自动运行。我做了一个由:

组成的mcve

distric.ads

with System;
with Interfaces.C;
package Division is
   --Neither of these work
   procedure DllMainCRTStartup ;
   pragma Export (StdCall, DllMainCRTStartup , "DllMainCRTStartup"); --Edited as noticed by Brian
   -- procedure DllMain
   -- pragma Export (StdCall, DllMain , "DllMain ");
   function Div (A : in INTEGER; B : in INTEGER) return INTEGER;
   pragma Export (C, Div, "MyDivision");
   -- --If I put this, it does not compile... maybe a wrong linkage option set?
   -- procedure AdaInit; 
   -- pragma Import (C, AdaInit, "adainit");
end Division;

distric.adb

with text_io;
package body Division is
   procedure DllMainCRTStartup  is begin --DllMain or DllMainCRTStartup
      text_io.put("INIT CODE YEAH!!!*************!"); --This does not execute :(
      --AdaInit;
   end DllMainCRTStartup ;
   function Div(A : in INTEGER; B : in INTEGER) return INTEGER is
      X : INTEGER := A/B;
   begin
      return X;
   end Div;
end Division;

和GPR:

library project Proj_Name is
  for Library_Name use "math";
  for Object_Dir use "obj";
  for Source_Dirs use ("src");
  for Library_Dir use "lib";
  for Library_Interface use ("Division");
  for Library_Kind use "dynamic";
  for Library_Options use ("-LC:GNAT2015libgcci686-pc-mingw324.9.3adalib",
                           "-LC:GNAT2015libgcci686-pc-mingw324.9.3adaliblibgnat");
end Proj_Name;

我正在用CTYPES测试Python的DLL。我用ctypes.cdll导入它,并且可以使用myDivision。但是,导入DLL时未运行INIT代码,因为未执行text_io。

另一方面,如果我在代码中添加Adainit过程,则在编译时会得到这样的东西:

undefined reference to `adainit'

非常感谢!

我不确定您如何知道未运行初始化代码?

我在MacOS上运行,但是ADA方面应该相似。我将此包装/主体写为您的简单版本:

package Division is
   function Div (A : in INTEGER; B : in INTEGER) return INTEGER;
   pragma Export (C, Div, "MyDivision");
end Division;
with Ada.Text_IO;
package body Division is
   function Div(A : in INTEGER; B : in INTEGER) return INTEGER is
      X : INTEGER := A/B;
   begin
      return X;
   end Div;
   procedure Test_For_Elaboration is
   begin
      Ada.Text_IO.Put_Line ("hello world!");
   end Test_For_Elaboration;
begin
   Test_For_Elaboration;
end Division;

使用此简单的GPR

library project Proj_Name is
  for Library_Name use "math";
  for Object_Dir use "obj";
  for Source_Dirs use ("src");
  for Library_Dir use "lib";
  for Library_Interface use ("Division");
  for Library_Kind use "dynamic";
end Proj_Name;

并使用此C代码进行了测试:

#include <stdio.h>
extern int MyDivision(int, int);
int main()
{
  printf("42 / 2 => %dn", MyDivision(42, 2));
  return 0;
}

结果是

$ ./caller 
hello world!
42 / 2 => 21

很清楚,对我来说,图书馆精心设计无需我做任何事情。

原因是您在项目文件中指定了Library_Interface,这意味着您正在构建独立库,

是一个包含必要代码以详细列出库中包含的ADA单元的库。独立的库是一种在更全球的系统中添加ADA子系统的便捷方法,该系统不在ADA中,因为它使ADA部分的详细说明主要是透明的。

您可以使用

来指定一个独立的动态库,该库自动初始化
for Library_Auto_Init use "false";

在这种情况下,您需要自己调用图书馆的初始化过程;它称为{library-name}init(在您的情况下,mathinit)。但是,您需要从主计划中调用它;需要在C

中声明它
extern void mathinit();

最新更新