我的问题很简单
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是关于...它是会成为0当rData是0?并成为40当rData有1?...
我在C#中使用DllImport方法有什么问题?
[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.