[英]How to get in Go a std::string from an exported function of a DLL?
我想加載自定義DLL(C ++一個)並調用它導出的函數? 這是我的Go代碼:
func main() {
dllForGo := syscall.MustLoadDLL("dllForGo.dll")
defer dllForGo.Release()
getHello:= dllForGo.MustFindProc("getHello")
r1, _, err := getHello.Call(0) // also tried with .Call() and still got the same error
}
這是我的DLL的C ++代碼:
std::string __stdcall getHello(void) {
int a = 1;
double b = 10;
return ("Hello-World !!"+std::to_string(a) + std::to_string(b));
}
我試圖強制使用__stdcall(並為此鏈接一個.def文件,因為我認為__declspec(dllexport)可能是個問題)。
但是,使用DUMPBIN,我可以看到getHello使用__cdecl調用約定。 這是個問題嗎?
這是我運行Go時遇到的錯誤:
Exception 0xc0000005 0x1 0x10 0x7fef0591327
PC=0x7fef0591327
syscall.Syscall(0x7fef05910d0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
D:/Go/src/runtime/syscall_windows.go:172 +0xf9
syscall.(*Proc).Call(0xc00004e420, 0xc000058090, 0x1, 0x1, 0x565520, 0x21, 0x2e06a0, 0x0)
D:/Go/src/syscall/dll_windows.go:146 +0x140
main.main()
D:/GoLand_Projects/dllLoad/main.go:58 +0x335
rax 0x22fdb8
rbx 0x9
rcx 0x30
rdi 0x9
rsi 0x0
rbp 0x22fdd9
rsp 0x22fd60
r8 0x30303030302e3031
r9 0x7fef1220000
r10 0x22fd90
r11 0x771a1f
r12 0xa
r13 0x9
r14 0x0
r15 0x0
rip 0x7fef0591327
rflags 0x10202
cs 0x33
fs 0x53
gs 0x2b
編輯
getHello函數實際上執行良好。 我修改了它以寫入文件:
std::string __stdcall getHello(void) {
std::ofstream outfile("D:\\test123.txt");
outfile << "getHello working!" << std::endl;
outfile.close();
int a = 1;
double b = 10;
return ("Hello-World !!"+std::to_string(a) + std::to_string(b));
}
...然后文件被寫入。 因此問題出在導出函數返回之后。 這使我認為我需要在Go部分中進行一些更改以“歡迎”返回的std :: string。
編輯2
如果我將導出函數的返回類型更改為void ,則Call會毫無例外地返回。 可以暗示它確實與調用約定有關嗎?
這是我從地鼠那里得到的答案:
處理對象非常棘手。 string是一個對象,它可能在某個地方有一個vtable,它也具有一個內部結構(盡管我忘記了它是什么,我想它可能類似於COM bstring或go slice,也許要檢查相關的c ++源代碼)。 調用方法將涉及查找調度表整體的地址並將其作為函數進行調用。 我建議您從C char *開始,然后逐步實現。
因此,我嘗試使用char **作為參數,可以在DLL函數中對其進行修改,並在Go中顯示所做的修改。 我也嘗試返回一個基本類型(int),它也起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.