douzang7928 2019-01-08 02:10 采纳率: 100%
浏览 402

如何从DLL的导出函数获取std :: string?

I want to load a custom DLL (C++ one) and call a function that it exports ? Here is my Go code:

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
}

Here the C++ code of my DLL:

 std::string __stdcall getHello(void) {
     int a = 1;
     double b = 10;
     return ("Hello-World !!"+std::to_string(a) + std::to_string(b));
}

I tried to force the use of __stdcall (and link a .def file for this, as I thought that maybe __declspec(dllexport) could be a problem ).

However, using DUMPBIN, I can see that getHello uses __cdecl calling convention. Is it a problem?

And here is the error I get when I run my 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

EDIT

The getHello function is actually well executed. I modified it to write to a file:

 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));
}

...and the file is written to. So the problem is at after the exported function returns. Which makes me think I need to change something in the Go part to "welcome" the returned std::string.

EDIT2

If I change the return type of the exported function to void then, the Call return without exception. Could it be an additional hint that it's indeed related to the calling convention ?

  • 写回答

1条回答 默认 最新

  • doumi7861 2019-01-08 10:38
    关注

    Here is the answer I got from a gopher:

    working with objects is tricky. string is an object, it probably has a vtable somewhere, it also has an internal structure (although I forget what it is, my guess would be it's similar to a COM bstring or a go slice, maybe check the relevant c++ sources). Calling methods would involve finding the address of the dispatch table entires and calling those as functions. I suggest you start with a C char * and work your way to that.

    So I tried by taking a char ** as argument , I could modify it in the DLL function and display the modification in Go. I also tried returning a basic type (int) and it worked also.

    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog