Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VB5 dll, how can I invoke the function from C# ( .NET 4.5 )

Tags:

c#

vb.net

interop

My Question is simple

VB.dll (VB5.0 I guess) includes these methods

Private Declare Function ffr_device_find Lib ".\ffr_32.dll" () As Boolean
Private Declare Function ffr_data_transceive_ex Lib ".\ffr_32.dll" (ByVal sp_sdata As String, ByVal sp_rdata As String) As Boolean

in C#.... ( .NET 4.5 )

[DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]
extern public static Boolean ffr_device_find();

[DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]
extern public static void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata);
// FYI, I tried [Out], out, and ref but to no avail.

The first one works great,

but the second one spilt this error.

A call to PInvoke function 'ffr_data_transceive_ex' has unbalanced the stack.
This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

FYI

This is a working code from VB... ( NOT INNER DLL SOURCES )

Dim st As String
Dim rData As String * 40

st = "4401" & "20202020202020202020202020202020"
Text1.Text = st
Cal_BCC
Call ffr_data_transceive_ex(Text1.Text, rData)
Text2.Text = rData

I don't even understand what Dim rData As String * 40 is about... will it become 0 when rData is 0? and become 40 when rData has 1? ...

What's wrong with my DllImport methods in C#???

like image 562
hina10531 Avatar asked Apr 14 '16 11:04

hina10531


1 Answers

   [DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]

It is not Cdecl. Visual Basic assumes the default, StdCall. You got away with it on the first function because it does not take any arguments. Not on the second since it imbalanced the stack, both the caller and the callee popped the arguments off the stack, forcing the MDA to step in and tell you about the drastic mishap.

Simply remove the property completely so you get the correct default in your C# program as well, CallingConvention.StdCall.

   void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata)

You cannot use string, strings are immutable in .NET. Use StringBuilder instead. Do make sure that its Capacity is large enough to be able to store the received data that the function writes. Guessing too low causes heap corruption, a very nasty bug to troubleshoot.

Also odds that it should be byte[], your question doesn't document the type of the returned data well enough. VB5 did not have a Byte type yet so a fixed string (like String * 40) was the next best choice. Doesn't work in .NET either, not all possible byte values have a corresponding Unicode codepoint. Use StringBuilder only if you know for a fact that the function only returns ASCII codes.

like image 168
Hans Passant Avatar answered Sep 19 '22 21:09

Hans Passant