【发布时间】:2021-12-05 14:48:59
【问题描述】:
我正在做一个项目,目前有以下结构:
- C# WPF 项目包含用户界面以及对外部方法的调用。
- 包含算法的 C++ DLL 项目。
- 包含算法的 ASM DLL 项目。
为简单起见,我们假设该算法不带参数并返回两个预定义数字的总和。
C++(二)项目中的函数签名和实现如下:
int Add(int x, int y)
{
return x + y;
}
extern "C" __declspec(dllexport) int RunCpp()
{
int x = 1, y = 2;
int z = Add(x, y);
return z;
}
下面是我在 C# 中调用函数的方式:
[DllImport("Algorithm.Cpp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int RunCpp();
这很好用——在 C# 中调用函数返回值 3,一切正常,没有抛出异常。
但是,我现在正在努力在 C# 代码中调用 ASM 过程。 我已经看到(并在一定程度上测试了自己)不可能直接在 C# 代码中调用 MASM DLL。但是,我听说可以在 C++ 中调用 ASM,然后在 C# 中调用该函数。
1. 我的第一个问题是——实际上可以直接在 C# 中调用 ASM 代码吗?当我尝试这样做时,我得到一个基本上说二进制代码不兼容的异常。
2.我曾尝试使用 C++ 间接调用 ASM DLL,虽然我没有遇到异常,返回值是“随机的”,就像在内存中留下的余数一样,例如:-7514271。这是我做错了什么,还是有其他方法可以做到这一点?
这是在 C++ 中调用 ASM 的代码:
typedef int(__stdcall* f_MyProc1)(DWORD, DWORD);
extern "C" __declspec(dllexport) int RunAsm()
{
HINSTANCE hGetProcIDDLL = LoadLibrary(L"Algorithm.Asm.dll");
if (hGetProcIDDLL == NULL)
{
return 0;
}
f_MyProc1 MyProc1 = (f_MyProc1)GetProcAddress(hGetProcIDDLL, "MyProc1");
if (!MyProc1)
{
return 0;
}
int x = 1, y = 2;
int z = MyProc1(x, y);
FreeLibrary(hGetProcIDDLL);
return z;
}
这里是用C#调用C++的代码:
[DllImport("Algorithm.Cpp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int RunAsm();
如果需要,这是MyProc1 的 ASM 代码:
Main.asm:
MyProc1 proc x: DWORD, y: DWORD
mov EAX, x
mov ECX, y
add EAX, ECX
ret
MyProc1 endp
Main.def:
LIBRARY Main
EXPORTS MyProc1
【问题讨论】:
-
听起来好像你编译了一个 32 位 dll 并尝试使用 64 位约定调用它。
-
事实并非如此——这三个项目都是在 64 位配置下编译的。
-
验证反汇编,然后仔细检查
x和y解析到什么。 -
我不是本机代码方面的专家,但据我所知,c++ 和程序集 dll 之间应该没有什么区别。你确定调用约定是正确的吗? Exporting from a dll 建议使用 stdcall。
-
@JonasH 将调用约定更改为 stdcall 并没有什么不同——算法的 C++ 版本仍然可以正常工作,而 ASM 版本仍然不能。
标签: c# c++ assembly masm masm64