How to use golang's c-shared .dll in C++
Asked Answered
I

0

1

I don't know much about C/C++ but I have some knowledge about golang. I was playing around with simple lib written in golang which I would like to use it in simple C++ program. I was thinking it would be possible after I generate .dll and .h files.

Here is my golang code

package main

import "C"

//export getHelloWord
func getHelloWord(word string) string {
    return word
}

func main() {

}

And I run the following command to generate .dll and .h files after installing TDM-GCC-64

go build -o cgo/lib/lib.dll -buildmode=c-shared cgo/lib.go

And here is my C++ file which loads .dll file generated by above steps and call the getHelloWorld function.

#include <windows.h>
#include <winbase.h>
#include <iostream>
using namespace std;

typedef string(__stdcall* f_getHelloWord)(string name);

int main()
{
    std::cout << "Starting program.\n";

    //Loading dll
    HINSTANCE  hModule = LoadLibrary(TEXT("lib/lib.dll"));

    if (!hModule) {
        std::cout << "could not load the dynamic library" << std::endl;
        return EXIT_FAILURE;
    }

    // resolve function address here
    f_getHelloWord fn = (f_getHelloWord)GetProcAddress(hModule, "getHelloWord");

    if (!fn) {
        std::cout << "could not locate the function" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "getHelloWord() returned " << fn("Hello World") << std::endl;

    return EXIT_SUCCESS;
}

When I compile and run the above program. It does not print returned word Hello World

Complete output is

Starting program.
getHelloWord() returned

C:\Users\TEMBO MTOTO\source\repos\cgo\x64\Debug\cgo.exe (process 27048) exited with code 0.
Press any key to close this window . . .

But when change go function to receive and return int instead of string it really works as expected. See code below..

package main

import "C"

//export getHelloWord
func getHelloWord(number int) int {
    return 7888 * number
}

func main() {

}

When I run program I get the following errors

#include <windows.h>
#include <winbase.h>
#include <iostream>
using namespace std;

typedef int(__stdcall* f_getHelloWord)(int n);

int main()
{
    std::cout << "Starting program.\n";

    //Loading dll
    HINSTANCE  hModule = LoadLibrary(TEXT("lib/lib.dll"));

    if (!hModule) {
        std::cout << "could not load the dynamic library" << std::endl;
        return EXIT_FAILURE;
    }

    // resolve function address here
    f_getHelloWord fn = (f_getHelloWord)GetProcAddress(hModule, "getHelloWord");

    if (!fn) {
        std::cout << "could not locate the function" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "getHelloWord() returned " << fn(10000) << std::endl;

    return EXIT_SUCCESS;
}

complete output is

Starting program.
getHelloWord() returned 78880000

So why string doesn't work? Any help will be much appreciated..

Code repository is available on GitHub

Intellect answered 3/5, 2022 at 9:49 Comment(14)
Your problem that getHelloWord returning GoString not std::string or char*. You should convert it to. str.assign(res.p, res.n); And the same for input parameterBluenose
because this is the struct of GoString struct { const char *p; ptrdiff_t n; }; Where p is the data and n is a length.Bluenose
@Bluenose Hi, Thanks for response which may have guide me to the right direction in fixing errors in c++. I have made some edit on how I use it. May you check if I use struct right now. I have made some editsIntellect
I think you should init length too. std::string golang = "Golang"; GoString input; input.p = golang.c_str(); input.n = golang.size();Bluenose
That's better. But now the real problem remains, how to use that c-shared lib because I still get errors like in this question here #53564865Intellect
Yes. As you can see in comments for the question, Visual studio not fully support cgo code because cgo use gcc compiler. These two compilers not fully compatible. Just try to manually change __SIZE_TYPE__ to long long. Probably it helps. But later you can have problems with linking.Bluenose
@Bluenose now I don't include any c headers, I have just generated a .dll file which now I am trying to use it in C++. I have update my question with new code. Could you take a lookIntellect
it could be a couple of error. First of all try to check result of every action in c++. #8697153 learn.microsoft.com/en-us/windows/win32/api/libloaderapi/…Bluenose
@Bluenose Thanks now I have succeeded in loading .dll file. Now the remaining problem is passing string in typedef. Int works but not string and I wonder why. I have made some edits as usual, may you have a lookIntellect
Because you load incorrect function. Your function with string looks like extern __declspec(dllexport) GoString getHelloWord(GoString name); not like extern __declspec(dllexport) GoString getHelloWord(std::string name);. GoString and std::string it's a different types. You should use GoStringBluenose
@Bluenose I don't want to use c-headers because it has incompatible types. I just want use .dll aloneIntellect
In this case just mode struct GoString to your fileBluenose
@Bluenose can you help me with that?Intellect
go.dev/play/p/TgR6yqR5lpNBluenose

© 2022 - 2025 — McMap. All rights reserved.