2016-11-23 35 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!我應該注意到沒有包初始化代碼... –