2016-11-23 33 views
1

执行的DLL构建的初始化代码蚊蚋导​​入时不自动运行。我这样做,包括在MCVE:的DllMain/DllMainCRTStartup不DLL

division.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; 

division.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:\GNAT\2015\lib\gcc\i686-pc-mingw32\4.9.3\adalib", 
          "-LC:\GNAT\2015\lib\gcc\i686-pc-mingw32\4.9.3\adalib\libgnat"); 
end Proj_Name; 

我正在用python测试dll,用ctypes。我用ctypes.CDLL导入它,我可以使用MyDivision。但是,导入dll时init代码不运行,因为text_io未执行。

在另一方面,如果我的AdaInit程序添加到代码编译时,我得到这样的:

undefined reference to `adainit' 

非常感谢您!

+0

“adainit”不是你写或提供。在任何Ada代码(例如“crt0.c”)运行之前(通常不可见),在main()在C程序中调用之前,框架通常会运行该命令来初始化Ada RTS。但是,这并不能解释为什么你的DLL启动没有被调用。奇怪的是:为什么导出的名称中有一个空格? –

+0

Ups ...错字。但是,我改变了它,但它没有工作:( – gccinac

回答

3

我不知道你是怎么知道的初始化代码没有运行?

我在MacOS上运行,但阿达方面应该是相似的。我写这个包投机/体作为一个简单的版本你的:

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 => %d\n", MyDivision(42, 2)); 
    return 0; 
} 

其结果是

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

这么清楚,对我来说,图书馆阐述称为没有我做任何事情。

的原因是,您在项目文件中指定Library_Interface,这意味着你正在构建一个stand-alone library,这

是包含必要的代码来阐述这包括在阿达单位库图书馆。一个独立的图书馆是一个阿达子系统添加到更具全球性的系统,其主要不是阿达,因为它使阿达部分大多是透明的制定的便捷方式。

您可以指定一个独立的动态库是自动初始化,使用

for Library_Auto_Init use "false"; 

在这种情况下,你需要自己调用库的初始化程序;它被称为{library-name}init(在你的情况下,mathinit)。但是你需要从你的主程序中调用它;它需要声明,在C

extern void mathinit(); 
+0

啊,你有解决方案!谢谢!我认为这足以导出函数运行时导入的名称DllMain。看来,这是不是要走的路,在你的解决方案中,你使用的开始 Test_For_Elaboration; end Division; – gccinac

+0

D'oh!我应该注意到没有包初始化代码... –