Reputation: 1438
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 ?
Upvotes: 1
Views: 1012
Reputation: 1438
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.
Upvotes: 0