我正在做一个项目,目前有以下结构:
- 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。我的第一个问题是-调用ASM代码实际上可能直接在c# ?当我尝试时,我得到一个异常,基本上说二进制代码是不兼容的。2
。我尝试使用c++间接调用ASM DLL,虽然我没有得到异常,但返回值是"随机",就像在内存中留下的余数一样,例如:-7514271。是我做错了什么,还是有其他方法可以做到这一点?
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();
Main.asm:
MyProc1
的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
调用ASM代码实际上可能直接在c#中?
两个项目的例子,c#和基于汇编的DLL。看起来你已经知道如何得到一个基于c++的DLL工作。项目名称与目录名称相同,xcs表示c#, xcall表示dll。我从空目录开始,创建空项目,然后将源文件移到目录中,然后将现有项目添加到每个项目中。
xcadll属性:
Configuration Type: Dynamic Library (.dll)
Linker | Input: xcadll.def
xcadll xcadll.def:
LIBRARY xcadll
EXPORTS DllMain
EXPORTS Example
xcadll xa。asm属性(对于发布版本,/Zi不需要):
General | Excluded From Build: No
General | Item Type: Custom Build Tool
Custom Build Tool | General | Command Line: ml64 /c /Zi /Fo$(OutDir)xa.obj xa.asm
Custom Build Tool | General | Outputs: $(OutDir)xa.obj
xcadll xa.asm:
includelib msvcrtd
includelib oldnames ;optional
.data
.data?
.code
public DllMain
public Example
DllMain proc ;return true
mov rax, 1
ret 0
DllMain endp
Example proc ;[rcx] = 0123456789abcdefh
mov rax, 0123456789abcdefh
mov [rcx],rax
ret 0
Example endp
end
xc Program.cs:
using System;
using System.Runtime.InteropServices;
namespace xcadll
{
class Program
{
[DllImport("c:\xcadll\x64\release\xcadll.dll")]
static extern void Example(ulong[] data);
static void Main(string[] args)
{
ulong[] data = new ulong[4] {0,0,0,0};
Console.WriteLine("{0:X16}", data[0]);
Example(data);
Console.WriteLine("{0:X16}", data[0]);
return;
}
}
}
对于调试,使用
[DllImport("c:\xcadll\x64\debug\xcadll.dll")]
xcs properties | debug |启用本机模式调试(勾选复选框)