我正在做一個專案,目前具有以下結構:
- 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
主檔案:
LIBRARY Main
EXPORTS MyProc1
uj5u.com熱心網友回復:
是否可以直接在 C# 中呼叫 ASM 代碼?
這個例子有兩個專案,C# 和基于程式集的 DLL。看起來您已經知道如何讓基于 C 的 DLL 作業。專案名稱與目錄名稱相同,C# 為 xcs,dll 為 xcadll。我從空目錄開始創建空專案,然后將源檔案移動到目錄中,然后將現有專案添加到每個專案中。
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
xcs\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 屬性 | 除錯 | 啟用本機模式除錯(選中該框)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/326205.html
