VB5 dll,如何从 C# ( .NET 4.5 ) 调用函数
VB5 dll, how can I invoke the function from C# ( .NET 4.5 )
我的问题很简单
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
在 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.
第一个很好用,
但是第二个溢出了这个错误。
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.
仅供参考
这是来自 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
是什么意思...当rData
是0
时它会变成0
吗?当 rData
有 1
时变成 40
? ...
我在 C# 中的 DllImport 方法有什么问题???
[DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]
不是Cdecl。 Visual Basic 采用默认值 StdCall。您在第一个函数中没有使用它,因为它不接受任何参数。不是第二次,因为它使堆栈不平衡,调用者和被调用者都将参数从堆栈中弹出,迫使 MDA 介入并告诉你这个严重的事故。
只需完全删除 属性 即可在 C# 程序中获得正确的默认值,CallingConvention.StdCall。
void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata)
您不能使用 string
,字符串在 .NET 中是不可变的。请改用 StringBuilder
。请确保其容量足够大,能够存储函数写入的接收数据。猜测太低会导致堆损坏,这是一个非常难以解决的错误。
也有可能它应该是 byte[]
,您的问题没有很好地记录返回数据的类型。 VB5 还没有 Byte 类型,因此固定字符串(如 String * 40)是下一个最佳选择。在 .NET 中也不起作用,并非所有可能的字节值都具有相应的 Unicode 代码点。仅当您知道该函数仅 returns ASCII 代码时才使用 StringBuilder。
我选择 Hans Passant 的上述答案
但是对于那些想要这个案例的精确解决方案的人,我会给你一些额外的信息和一些代码片段。
第一
正如 Hans Passant 所说,CallingConvention
应该被淘汰。
第二
正如 Hans Passant 所说,不应将字符串传递到函数中。更准确地说,第一个参数可以作为 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);
这非常有用,它 returns 是 ForCardHex
的预期值。你应该使用 char[]
。我无法将 byte[]
传递给函数。
感谢所有评论者和回答者。
我的问题很简单
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
在 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.
第一个很好用,
但是第二个溢出了这个错误。
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.
仅供参考
这是来自 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
是什么意思...当rData
是0
时它会变成0
吗?当 rData
有 1
时变成 40
? ...
我在 C# 中的 DllImport 方法有什么问题???
[DllImport("FFR_32.dll", CallingConvention = CallingConvention.Cdecl)]
不是Cdecl。 Visual Basic 采用默认值 StdCall。您在第一个函数中没有使用它,因为它不接受任何参数。不是第二次,因为它使堆栈不平衡,调用者和被调用者都将参数从堆栈中弹出,迫使 MDA 介入并告诉你这个严重的事故。
只需完全删除 属性 即可在 C# 程序中获得正确的默认值,CallingConvention.StdCall。
void ffr_data_transceive_ex([Out] string sp_sdata, [Out] string sp_rdata)
您不能使用 string
,字符串在 .NET 中是不可变的。请改用 StringBuilder
。请确保其容量足够大,能够存储函数写入的接收数据。猜测太低会导致堆损坏,这是一个非常难以解决的错误。
也有可能它应该是 byte[]
,您的问题没有很好地记录返回数据的类型。 VB5 还没有 Byte 类型,因此固定字符串(如 String * 40)是下一个最佳选择。在 .NET 中也不起作用,并非所有可能的字节值都具有相应的 Unicode 代码点。仅当您知道该函数仅 returns ASCII 代码时才使用 StringBuilder。
我选择 Hans Passant 的上述答案
但是对于那些想要这个案例的精确解决方案的人,我会给你一些额外的信息和一些代码片段。
第一
正如 Hans Passant 所说,CallingConvention
应该被淘汰。
第二
正如 Hans Passant 所说,不应将字符串传递到函数中。更准确地说,第一个参数可以作为 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);
这非常有用,它 returns 是 ForCardHex
的预期值。你应该使用 char[]
。我无法将 byte[]
传递给函数。
感谢所有评论者和回答者。