0

how can i use C++ dll for my vb.net Project ?

i have this c++ dll function that i want to call from vb.net :

typedef void(CALLBACK *fRemoteConfigCallback)(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData);
NET_DVR_API LONG __stdcall NET_DVR_StartRemoteConfig(LONG lUserID, DWORD dwCommand, LPVOID lpInBuffer, DWORD dwInBufferLen, fRemoteConfigCallback cbStateCallback, LPVOID pUserData);
NET_DVR_API LONG __stdcall NET_DVR_GetNextRemoteConfig(LONG lHandle, void* lpOutBuff, DWORD dwOutBuffSize);

Here's the code that i made on my C# Wrapper to call the PInvoke :

public delegate void fRemoteConfigCallback(uint lCommand, IntPtr lpBuffer, uint dwBufLen, IntPtr pUserData);
[DllImport("HCNetSDK.dll", CallingConvention = CallingConvention.StdCall)]
public static extern long NET_DVR_StartRemoteConfig(long lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferLen, fRemoteConfigCallback cbStateCallback, IntPtr pUserData);
[DllImport("HCNetSDK.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int NET_DVR_GetNextRemoteConfig(long lHandle, IntPtr lpOutBuff, uint dwOutBuffSize);

and i call the wrapper with this code :

Dim m_struAttendanceRecordCfg As NET_DVR_ATTENDANCE_RECORD_CFG = New NET_DVR_ATTENDANCE_RECORD_CFG()
a = Marshal.AllocHGlobal(Marshal.SizeOf(m_struAttendanceRecordCfg))
'error on this line
iret = NET_DVR_GetNextRemoteConfig(mHandle, a, Marshal.SizeOf(m_struAttendanceRecordCfg))
Marshal.StructureToPtr(m_struAttendanceRecordCfg, a, False)
Marshal.FreeHGlobal(a)

Based on what i search on google, it's because some data type of the variables doesn't match with the c++ dll ? what should i change so this code can works ? Thanks in advance.

EDIT : Here's my edited c# wrapper :

[DllImport("HCNetSDK.dll")]
public static extern int NET_DVR_StartRemoteConfig(int lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferLen, fRemoteConfigCallback cbStateCallback, IntPtr pUserData);
[DllImport("HCNetSDK.dll")]
public static extern int NET_DVR_GetNextRemoteConfig(int lHandle, IntPtr lpOutBuff, uint dwOutBuffSize);

vb.net code

Dim m_struSearchInfoCond As NET_DVR_SEARCH_INFO_COND = New NET_DVR_SEARCH_INFO_COND()
Dim m_struAttendanceRecordCfg As NET_DVR_ATTENDANCE_RECORD_CFG = New NET_DVR_ATTENDANCE_RECORD_CFG()

Dim a As IntPtr
a = Marshal.AllocHGlobal(Marshal.SizeOf(m_struSearchInfoCond))
Dim sizeOfA As UInt16 = Marshal.SizeOf(a)
'if i change mHandle as Uint32, it throw error Overflow
Dim mHandle As Long = NET_DVR_StartRemoteConfig(lUser, NET_DVR_GET_ATTENDANCE_RECORD_INFO,a, sizeOfA, Nothing, Nothing)
If mHandle < 0 Then
   sizeOfA = NET_DVR_GetLastError()
End If
Marshal.StructureToPtr(m_struSearchInfoCond, a, False)
Marshal.FreeHGlobal(a)

Dim iret As Long = 0
While mHandle >= 0
    a = Marshal.AllocHGlobal(Marshal.SizeOf(m_struAttendanceRecordCfg))
    'if i change mHandle to long and pass it to this API (NET_DVR_GetNextRemoteConfig), it throw error "has unbalanced stack"
    lUser = NET_DVR_GetNextRemoteConfig(mHandle, a, Marshal.SizeOf(m_struAttendanceRecordCfg))
    Marshal.StructureToPtr(m_struAttendanceRecordCfg, a, False)
    Marshal.FreeHGlobal(a)
    fid = m_struAttendanceRecordCfg.dwEmployeeNo
End While
XMozart
  • 879
  • 2
  • 10
  • 22
  • `LONG` is `int`, not `long`. See https://learn.microsoft.com/en-us/dotnet/framework/interop/marshaling-data-with-platform-invoke – canton7 Mar 14 '19 at 09:35
  • StdCall is by default. If your callback is cdecl, you might want to add the `[UnmanagedFunctionPointer(CallingConvention.Cdecl)]` attribute to it (plus change long to int indeed) – Simon Mourier Mar 14 '19 at 09:50
  • changed it from long to Uint32, i got error ': 'Arithmetic operation resulted in an overflow.' ? when i call NET_DVR_StartRemoteConfig it returned 18446744073709551615 (more than Uint32 maximum value), i'm on x64bit machine btw – XMozart Mar 14 '19 at 09:59
  • @XMozart `LONG` (the winapi type) is 32 bits on x86 and on x64, see https://stackoverflow.com/questions/384502/what-is-the-bit-size-of-long-on-64-bit-windows . Which line exactly throws that exception? – canton7 Mar 14 '19 at 11:20
  • @XMozart are you sure that your C# is compiled with the same bitness as your C++? Note that by default C# applications run as 32-bit on 64-bit platforms: make sure you set your Platform Target to x86 or x64 as appropriate, and *not* "Any CPU" – canton7 Mar 14 '19 at 11:21
  • @XMozart : `LONG` maps to `int` (`Int32`), _**not**_ `long` nor `uint`. The function cannot return a value larger than that unless the C++ declaration you've posted does _not_ match the compiled DLL. – Visual Vincent Mar 14 '19 at 11:49
  • That's why I think the problem (the `OverflowException` after fixing the `LONG`s) is with those `IntPtrs` and mis-matched bitness, which is why I asked the question I did. – canton7 Mar 14 '19 at 12:44
  • @canton7 : Though mismatched bitness would cause an [`BadImageFormatException`](https://learn.microsoft.com/en-us/dotnet/api/system.badimageformatexception) to be thrown as a 32-bit application cannot load 64-bit code _at all_, and vice versa. – Visual Vincent Mar 14 '19 at 15:04
  • @canton7 yes, on my C# Project Properties - Build, i set the platform target to x86 , please see my edited questions. that's why i really confused because i declared it on my c# as int which mean it couldn't get return value more than what int32.maxValue has. i don't know about what platform was the c++ dll compiled – XMozart Mar 14 '19 at 16:02

0 Answers0