C++ DLL über DLL Import einbinden

01/08/2008 - 20:05 von Chris Oertel | Report spam
Hallo,
ich habe ein Problem aus VB.NET eine Funktion in einer C++ DLL anzusprechen.
Der Header der C++ Funktion ist folgender:

// Liefert Interface-Informationen aus der Interfaceliste vom Interface an
index
// returns detailed informations of the interface in the device list found
on index
// index = 0...numDevs
// PortIndex = Pointer to a DWORD, returns the port to open the interface
// pDescription = Pointer to a char array, returns the description
// Length = the length of the char array
bool Dmx4allGetInterfaceDetail(DWORD index, DWORD* PortIndex, char*
pDescription,int Length);

Wenn ich versuche die DLL so anzusprechen, dann ende ich in einem
FatalExecutionEngineError:

<DllImport("DMX4ALL.dll", EntryPoint := "GetInterfaceDetail",
CallingConvention := CallingConvention.Winapi)> _
Public Shared Function GetInterfaceDetail(ByVal index As Integer, ByRef
PortIndex As Integer, ByRef description As StringBuilder, ByVal Length As
Integer) As Boolean
End Function

Nach einigem Googlen habe ich folgendes gefunden, um die verwendeten Pointer
zu mappen und meinen Code so umgestellt:

<DllImport("DMX4ALL.dll", EntryPoint := "GetInterfaceDetail",
CallingConvention := CallingConvention.Winapi)> _
Private Shared Function wrapped_DMX4ALL_GetInterfaceDetail(ByVal index As
Integer, ByRef PortIndex As Integer, ByRef description As IntPtr, ByVal
Length As Integer) As Boolean
End Function

Public Shared Sub GetInterfaceDetail(ByVal index As Integer, ByRef PortIndex
As Integer, ByRef Description As String)
Dim gchandle As GCHandle
Dim ssDescBuffer As New String(" "C, 50)
Dim siDescBufferLength As Integer = ssDescBuffer.Length
Dim siPort As Integer = 0

gchandle = New GCHandle()
Dim intPtrDesc As IntPtr = IntPtr.Zero
Dim bArr As Byte() = (New UTF8Encoding()).GetBytes(ssDescBuffer)
Try
getPointer(bArr, 0, gchandle, intPtrDesc)

wrapped_DMX4ALL_GetInterfaceDetail(index, siPort, intPtrDesc,
siDescBufferLength)
'PortIndex = siPort;
ssDescBuffer = Marshal.PtrToStringAuto(intPtrDesc)
Finally
gchandle.Free()
End Try
Description = ssDescBuffer
End Sub

Private Shared Sub getPointer(ByVal buffer As Byte(), ByVal bufferOffset As
Integer, ByRef bufferHandle As GCHandle, ByRef bufferPtr As IntPtr)
If buffer Is Nothing Then
Return
End If
bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned)
bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset)
End Sub

MIt der Demo aus Google hjat das auch wunderbar geklappt, nur in meinem Fall
mit der spezifischen DLL habe ich dann folgende Probleme:

-intPtrDesc zeigt scheinbar immer auf einen Leerstring
-gchandle ist bis zum Aufruf von wrapped_DMX4ALL_GetInterfaceDetail gültig
(allocated = true), nach dem Aufruf allerdings allocated = false (was sicher
auch den Leerstring erklàrt).

Da ich mich mit Pointer als alter VB Jünger nicht so auskenne, stehe ich
gerade etwas ratlos da. Kann mir jemand sagen, was ich hier falsch mache oder
wie man richtig mit C++ Pointer in VB.NET umgeht?

Danke,
Christian
 

Lesen sie die antworten

#1 Thomas Scheidegger
01/08/2008 - 20:17 | Warnen spam
Hallo Chris


// pDescription = Pointer to a char array, returns the description
bool Dmx4allGetInterfaceDetail(DWORD index, DWORD* PortIndex, char*
pDescription,int Length);
<DllImport("DMX4ALL.dll", EntryPoint := "GetInterfaceDetail",
CallingConvention := CallingConvention.Winapi)> _
Public Shared Function GetInterfaceDetail(ByVal index As Integer, ByRef
PortIndex As Integer, ByRef description As StringBuilder, ByVal Length As
Integer) As Boolean




StringBuilder ist schon ein Verweistyp, nimm ByVal:

ByVal description As StringBuilder


und vor Aufruf angemessene SB-Kapazitàt, nur zB
Dim sb As New StringBuilder(100)



Thomas Scheidegger - 'NETMaster'
http://dnetmaster.net/

Ähnliche fragen