我使用汇编程序dll编写程序并尝试将汇编程序中的函数添加到我的c#程序中,这将从c#中返回字符串中的字符数量。
c#program:
[DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int zlicz(string tab);
private void button4_Click(object sender, EventArgs e)
{
int pom=0;
string tab = "1111111fdgsdgdgd";
pom = zlicz(tab);
}
和我的汇编代码:
myprocedure proc
push ebp
mov ebp, esp
mov ebx, [ebp+8] ; begin of char array
xor eax, eax
check:
cmp byte ptr[ebx],0 ; if end of array
je endprocedure
inc ebx
inc eax
jmp check
endprocedure:
pop ebp
ret
myprocedure endp
但它仅适用于具有超过100个元素的字符串,例如7个元素,此程序崩溃并出现错误:
GUI.exe中出现未处理的“System.ExecutionEngineException”类型异常
有人可以帮我解决这个问题,因为我想使用少于100个元素的字符串。
答案 0 :(得分:0)
动态链接库需要一个以null结尾的ansi字符串,并且您传递的是一个前缀为BSTR的长度
根据MSDN documentation, Default Marshaling for Strings,以下签名:
DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure(string tab);
将字符串变量选项卡封送为UnmanagedType.BStr
虽然根据这张表:
UnmanagedType.BStr (default)
A COM-style BSTR with a prefixed length and Unicode characters.
UnmanagedType.LPStr
A pointer to a null-terminated array of ANSI characters.
UnmanagedType.LPWStr
A pointer to a null-terminated array of Unicode characters.
您需要将标签变量标记为UnmanagedType.LPStr
这可以通过以下方式轻松实现:
DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure([MarshalAs(UnmanagedType.LPStr)] string tab);
然而,
这会将字符串编组为每个字符一个字节,这意味着,您传递的是ANSI字符串,而不支持unicode。
要支持unicode字符,只需将非托管类型规范更改为UnmanagedType.LPWStr
DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure([MarshalAs(UnmanagedType.LPWStr)] string tab);
但是,在这种情况下,您还应该更新汇编代码以读取unicode字符(我可以想象这不是一个简单的任务)
注意:我通过使用MASM32编译dll并从C#调用它来复制该问题,并成功测试了建议的解决方案LPStr。