AccessViolationException when calling a C++ function from VB.NET

165 views Asked by At

I created a DLL with one exported function in C++, this way:

extern "C" __declspec(dllexport) int __stdcall AlmacenarPedido(DWORD dwTelefono, LPCTSTR lpszFechaPedido, LPCTSTR lpszHoraPedido, LPCTSTR lpszCodigoInterno, LPCTSTR lpszDescripcionProducto,
                                          int iCantidadProducto, int iValorUnitario, LPCTSTR lpszFechaEntrega, LPCTSTR lpszHoraEntrega, int iKilosProducto, 
                                          LPCTSTR lpszFechaDespacho, LPCTSTR lpszHoraDespacho)

I am trying to call this function from VB.NET.

This is the DllImport:

<DllImport("ComTesting.dll", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
Function AlmacenarPedido(ByVal dwTelefono As Long, ByVal lpszFechaPedido As String, ByVal lpszHoraPedido As String,
                         ByVal lpszCodigoInterno As String, ByVal lpszDescripcionProducto As String,
                         ByVal iCantidadProducto As Integer, ByVal iValorUnitario As Integer, ByVal lpszFechaEntrega As String, ByVal lpszHoraEntrega As String,
                         ByVal iKilosProducto As Integer, ByVal lpszFechaDespacho As String, ByVal lpszHoraDespacho As String) As Integer
End Function

And this is the actual call:

Sub Main()
    Dim lTelefono As Long = 229188562
    Dim sFechaPedido As String = "16/12/2016"
    Dim sHoraPedido As String = "20:30"
    Dim sCodigoInterno As String = "123456"
    Dim sDescripcionProducto As String = "CARGA CODIGAS CATALITICO 15 KILOS"
    Dim iCantidadProducto As Integer = 2
    Dim iValorUnitario As Integer = 14000
    Dim sFechaEntrega As String = "19/12/2016"
    Dim sHoraEntrega As String = "15:14"
    Dim iKilosProducto As Integer = 15
    Dim sFechaDespacho As String = "19/12/2016"
    Dim sHoraDespacho As String = "10:00"
    Dim iPedido As Integer = AlmacenarPedido(lTelefono, sFechaPedido, sHoraPedido, sCodigoInterno, sDescripcionProducto, iCantidadProducto, iValorUnitario, sFechaEntrega, sHoraEntrega, iKilosProducto, sFechaDespacho, sHoraDespacho)
    Console.WriteLine(iPedido)
End Sub

When the calling is made, AccessExceptionException is thrown.

Any help, please?

EDIT:

StackTrace:

   en Testing.MainModule.AlmacenarPedido(Int64 dwTelefono, String& lpszFechaPedido, String& lpszHoraPedido, String& lpszCodigoInterno, String& lpszDescripcionProducto, Int32 iCantidadProducto, Int32 iValorUnitario, String& lpszFechaEntrega, String& lpszHoraEntrega, Int32 iKilosProducto, String& lpszFechaDespacho, String& lpszHoraDespacho)
   en Testing.MainModule.Main() en C:\WorkingFolder\Proyectos\Lipigas\GasProvidencia\Testing\MainModule.vb:lĂ­nea 37
   en System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   en System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   en Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   en System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   en System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   en System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   en System.Threading.ThreadHelper.ThreadStart()
2

There are 2 answers

3
selbie On

I see the problem. The first parameter, dwTelefono, is declared as DWORD in the DLL, but as a Long in the Pinvoke declaration. DWORDs are 32-bit and Longs in VB.NET are 64-bit. Hence, the stack is getting setup wrong when the DLL is invoked.

Change the first parameter declaration from this:

 Function AlmacenarPedido(ByVal dwTelefono As Long,

To this:

Function AlmacenarPedido(ByVal dwTelefono As UInt32,

I tested this out locally and confirmed it fixed it.

2
paulsm4 On
  1. Regarding your first problem: selbie is absolutely correct. VB.Net "Long" <> C/C++ "DWORD". I believe you fixed that.

  2. Similarly, regarding your second problem, String& lpszFechaPedido != LPCTSTR lpszFechaPedido! You need <MarshalAs(UnmanagedType.LPStr): return string from c++ function to VB .Net

Please read up on interfacing "Native code" with VB.Net - that will greatly simplify your work:

MSDN: Calling Native Functions from Managed Code

MSDN: Overview of Marshaling in C++