VB5 DLL,如何从C#(.NET 4.5)调用该函数

hin*_*531 7 c# vb.net interop

我的问题很简单

VB.dll(VB5.0我猜)包括这些方法

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
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

第一个效果很好,

但第二个溢出了这个错误.

对PInvoke函数'ffr_data_transceive_ex'的调用使堆栈失衡.
这很可能是因为托管PInvoke签名与非托管目标签名不匹配.检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配.

FYI

这是来自VB的工作代码...(不是内部DLL源)

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
Run Code Online (Sandbox Code Playgroud)

我甚至不明白什么Dim rData As String * 40是关于...它是会成为0rData0?并成为40rData1?...

我在C#中使用DllImport方法有什么问题?

Han*_*ant 7

   [DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]
Run Code Online (Sandbox Code Playgroud)

它不是Cdecl.Visual Basic采用默认的StdCall.你在第一个函数上侥幸成功,因为它不带任何参数.不是第二次,因为它使堆栈失衡,调用者和被调用者都会从堆栈中弹出参数,迫使MDA介入并告诉你剧烈的事故.

只需完全删除该属性,以便在C#程序中获得正确的默认值,CallingConvention.StdCall.

   void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata)
Run Code Online (Sandbox Code Playgroud)

你不能使用string,字符串在.NET中是不可变的.请StringBuilder改用.确保其容量足够大,以便能够存储函数写入的接收数据.猜测太低会导致堆损坏,这是一个非常讨厌的错误.

它也应该是可能的byte[],你的问题并不能很好地记录返回数据的类型.VB5没有字节类型,所以固定字符串(如String*40)是下一个最佳选择.在.NET中也不起作用,并非所有可能的字节值都具有相应的Unicode代码点.仅当您知道该函数仅返回ASCII代码的事实时才使用StringBuilder.