我想加载自定义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。
EDIT2
如果我将导出函数的返回类型更改为 void ,则Call会无例外地返回。可以暗示它确实与调用约定有关吗?
答案 0 :(得分:0)
这是我从地鼠那里得到的答案:
处理对象非常棘手。字符串是一个对象,它可能有一个 vtable的某个地方,它也具有内部结构(尽管我忘记了 这是什么,我猜是类似于COM bstring或go 切片,也许检查相关的c ++来源)。调用方法将 涉及查找调度表整体的地址并调用 那些作为功能。我建议您从C char *开始,然后 的方式。
因此,我尝试使用char **作为参数,我可以在DLL函数中对其进行修改,并在Go中显示所做的修改。我还尝试返回一个基本类型(int),它也起作用。