2013-10-09 4 views
2

vb.net에서 관리되지 않는 C++ 작업으로 DllExport를 가져 오려고합니다.Robert Giesecke의 관리되지 않는 내보내기

Visual Studio 2012에서 Robert Giesecke's Unmanaged Exports을 사용 중이며이 내용을 따르려고했지만 very helpful hints입니다. 내 * .cpp 및 * .h 파일이있는 디렉토리의 빌드 빌드 작업에 의해 .Net 프로젝트에서 dll을 복사합니다.

나는 dumpbin /EXPORTS Nugget.Discovery.dll 내 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 해킹은 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! 스테판

+1

DllExport는 IL을 수정하여 작동합니다. 그래서 메서드 호출은 작동하지 않습니다. 클래스를 내부 클래스로 표시하고 메소드를 비공개 클래스로 표시하는 것이 가장 좋습니다. 따라서 호출 할 기회가 적습니다. –

3

DllExport의 일부로 .lib 파일이 생성됩니다. 이를 사용하여 LoadLibrary/GetProcAddress 대신 일반 C++ 링커를 사용할 수 있습니다.

네이티브 측면에, 당신이 게시 된 관리 코드에서 시작 : 당신이 관리되지 않는 프로젝트의 설정에서

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을 출력 디렉터리에 복사합니다.