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

Nux
  • 5,890
  • 13
  • 48
  • 74
  • 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 parameter – isavinof May 03 '22 at 14:29
  • because this is the struct of GoString struct { const char *p; ptrdiff_t n; }; Where `p` is the data and `n` is a length. – isavinof May 03 '22 at 14:31
  • @isavinof 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 edits – Nux May 03 '22 at 18:11
  • I think you should init length too. `std::string golang = "Golang"; GoString input; input.p = golang.c_str(); input.n = golang.size();` – isavinof May 03 '22 at 19:23
  • 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 https://stackoverflow.com/questions/53564365/cgo-generated-sources-fail-to-compile-on-mvc – Nux May 03 '22 at 19:58
  • 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. – isavinof May 03 '22 at 20:26
  • @isavinof 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 look – Nux May 04 '22 at 07:59
  • it could be a couple of error. First of all try to check result of every action in c++. https://stackoverflow.com/questions/8696653/dynamically-load-a-function-from-a-dll https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress – isavinof May 04 '22 at 08:42
  • @isavinof 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 look – Nux May 04 '22 at 17:05
  • 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 GoString – isavinof May 05 '22 at 08:51
  • @isavinof I don't want to use c-headers because it has incompatible types. I just want use `.dll` alone – Nux May 05 '22 at 10:24
  • In this case just mode struct GoString to your file – isavinof May 05 '22 at 10:33
  • @isavinof can you help me with that? – Nux May 05 '22 at 10:38
  • https://go.dev/play/p/TgR6yqR5lpN – isavinof May 05 '22 at 10:38

0 Answers0