我的问题是简单的
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 Booleanin 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.第一个工作很棒的,
但第二个错误导致了这个错误。
对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我甚至不明白Dim rData As String * 40是怎么回事.当0是rData时,它会变成0吗?当rData有1的时候变成1?
我的DllImport方法在C#中有什么问题?
发布于 2016-04-14 12:12:01
[DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]不是Cdecl。Visual假定默认为StdCall。在第一个函数中,您可以不使用它,因为它不带任何参数。由于堆栈不平衡,调用方和被调用方都会从堆栈中弹出参数,迫使MDA介入并告诉您严重的问题。
只需完全删除该属性,就可以在C#程序中获得正确的默认设置,CallingConvention.StdCall。
void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata)您不能使用string,字符串在.NET中是不可变的。请使用StringBuilder。一定要确保它的容量足够大,能够存储函数写入的接收数据。猜测过低会导致堆损坏,这是一个非常讨厌的错误,很难排除。
还有可能是byte[],您的问题没有很好地记录返回数据的类型。VB5还没有字节类型,所以固定字符串(比如string * 40)是下一个最佳选择。也不能在.NET中工作,并不是所有可能的字节值都有相应的Unicode代码点。只有当您知道函数只返回StringBuilder代码时,才使用ASCII。
发布于 2016-04-15 00:07:54
我选择汉斯?帕桑特?的答案。
但是对于那些想要这个案例的精确解决方案的人,我会给你们一些额外的信息和一些代码片段。
First
就像汉斯·帕桑所说的,CallingConvention应该被抛弃。
第二
正如Hans所说,字符串不应该传递到函数中。更准确地说,第一个参数可以作为string类型传递。但是第二个应该是显式长度的char[]。
我对此进行了测试,当长度不同时,它会引发另一个错误。
工作代码
extern public static void ffr_data_transceive_ex([Out] string sp_sdata, [Out] char[] sp_rdata);必需成分
// To pass the second parameter.
// Because the dll returns 40 length characters, this should be specified as length '40'
char[] ForCardHex = new char[40];
// Command is an already defined protocol format, like "200080581028000001"
// , which can be taken as string.
ffr_data_transceive_ex(Command, ForCardHex);这非常有效,它在ForCardHex上返回预期值。您应该使用char[]。我无法将byte[]传递到函数中。
感谢所有的评论员和回答者。
https://stackoverflow.com/questions/36621884
复制相似问题