2013-10-09 42 views
2

我試圖從vb.net獲得一個DllExport給非託管C++工作。Robert Giesecke的非託管導出

我在使用Robert Giesecke's Unmanaged Exports與Visual Studio 2012並試圖遵循此very helpful hints。我在。* .cpp和* .h文件所在的目錄中通過post build動作從.Net項目複製dll。

我檢查了我的DLL與dumpbin /EXPORTS Nugget.Discovery.dll,它告訴我,有出口:

File Type: DLL 
Section contains the following exports for \Nugget.Discovery.dll 
00000000 characteristics 
52554A05 time date stamp Wed Oct 09 14:20:21 2013 
    0.00 version 
     0 ordinal base 
     2 number of functions 
     2 number of names 
ordinal hint RVA  name 
     0 0 0000532E StartAnnouncing 
     1 1 0000533E StopAnnouncing 
Summary 
    2000 .reloc 
    4000 .rsrc 
    2000 .sdata 
    4000 .text 

但是,如果我嘗試使用

#import "Nugget.Discovery.dll" 
    void StartAnnouncing(int serial); 

它導入cpp文件,我得到一個智能感知錯誤並嘗試編譯後出現一個錯誤:

IntelliSense: cannot open source file "Debug/Nugget.Discovery.tlh" 
error C1083: Cannot open type library file: 'nugget.discovery.dll': Fehler beim Laden der Typbibliothek/DLL. 

任何想法我做錯了什麼?

此致敬禮! 斯特凡

+3

你對此非常不利。 #import指令旨在導入COM組件的類型庫。 Giesecke hack不會生成COM組件,它會生成只包含導出函數的普通DLL。您必須在您的C++代碼中使用LoadLibrary和GetProcAddress才能使用它。實際上在C#中創建COM組件非常簡單,只需使用[ComVisible]屬性即可。然而,在C++中使用COM組件有一條學習曲線,你很可能從那個底部開始。 –

回答

2

好,感謝Hans Passant我來到這個解決方案:

這是我的代碼在管理方面:

Imports System.Runtime.InteropServices 
Imports RGiesecke.DllExport 

Public NotInheritable Class Beacon 

Private Sub New() 
End Sub 

Private Shared _nuggetAnnouncement As NuggetAnnouncement 

' ReSharper disable UnusedMember.Local 
''' <remarks>Cannot be called from managed code!</remarks> 
<DllExport("StartAnnouncing", CallingConvention.StdCall)> 
Private Shared Sub StartAnnouncingNative(serial As Integer) 
    StartAnnouncing(serial) 
End Sub 

''' <remarks>Cannot be called from managed code!</remarks> 
<DllExport("Test", CallingConvention.StdCall)> 
Private Shared Function TestNative() As Integer 
    Return Test() 
End Function 
' ReSharper restore UnusedMember.Local 

Public Shared Sub StartAnnouncing(serial As Integer) 
    'do something 
End Sub 

Public Shared Function Test() As Integer 
    Return 42 
End Function 

End Class 

有趣的是,我不能叫標有<DllExport>功能從託管代碼(即使它們是公用的)。

而且這是在本機端代碼:

typedef void (CALLBACK* StartAnnouncingType)(int); 
typedef int (CALLBACK* TestType)(void); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
HINSTANCE dllHandle = NULL; 
StartAnnouncingType StartAnnouncingPtr = NULL; 
TestType TestPtr = NULL; 
wchar_t dllNameWide[64]; 
int size = mbstowcs(dllNameWide, "Nugget.Discovery.dll", sizeof(dllNameWide)); 
dllHandle = LoadLibrary(dllNameWide); 
if (NULL != dllHandle) 
{ 
    //Get pointer to our function using GetProcAddress: 
    StartAnnouncingPtr = (StartAnnouncingType)GetProcAddress(dllHandle,"StartAnnouncing"); 
    TestPtr = (TestType)GetProcAddress(dllHandle,"Test"); 
    int test; 
    if (NULL != TestPtr) test = TestPtr(); 
    int serial = 1; 
    if (NULL != StartAnnouncingPtr) StartAnnouncingPtr(1); 
    //Free the library: 
    FreeLibrary(dllHandle);  
} 
} 

是否有其他更好的解決方案?

Ciao! Stefan

+1

DllExport通過修改IL工作。這就是爲什麼調用這些方法不起作用。最好將班級標記爲內部班級,並將班級標記爲私人班級,這樣可以減少對班級的打電話。 –

3

作爲DllExport的一部分,會生成一個.lib文件。您可以使用它來使用普通的C++鏈接器而不是LoadLibrary/GetProcAddress。

從您發佈的託管代碼開始,在本機端:

extern CALLBACK void StartAnnouncingType(int serial); 
extern CALLBACK int TestType(void); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int test = TestPtr(); 
    StartAnnouncingPtr(1); 
} 

在您的非託管項目的設置,添加Nugget.Discovery.lib到項目屬性:配置屬性 - >連接器 - >輸入。並將Nugget.Discovery.dll複製到輸出目錄。