How to get in Go a std::string from an exported function of a DLL?

1

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 ?

c++
go
dll
64bit
asked on Stack Overflow Jan 8, 2019 by Bonjour123 • edited Jan 8, 2019 by Bonjour123

1 Answer

0

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.

answered on Stack Overflow Jan 8, 2019 by Bonjour123

User contributions licensed under CC BY-SA 3.0