Using Go in C++ - c++

linux Debian Buster
go version go1.11.6 linux/amd64
gcc version 8.3.0 (Debian 8.3.0-6)
libmylib.go
package main
import "C"
import (
"fmt"
)
func say(text string) {
fmt.Println(text)
}
func main(){}
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <string>
void say(std::string text);
#endif
main.cpp
#include <string>
#include "mylib.h"
using namespace std;
int main() {
string text = "Hello, world!";
say(text);
return 0;
}
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
g++ -L/path/to/lib/ -lmylib main.cpp -o my-test-program
/usr/bin/ld: /tmp/ccu4fXFB.o: in function 'main':
main.cpp:(.text+0x53): undefined reference to `say(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)' collect2: error: ld returned 1 exit status
with change: package main -> package mylib
CGO_ENABLED=1 go build -o libmylib.so -buildmode=c-shared libmylib.go
-buildmode=c-shared requires exactly one main package

You have to use GoString rather than std::string in the C++ version. The error message you are getting is because of the type mismatch, manifesting as a link-time error.
See the cgo reference.
Here's a working example. There's a few differences from yours. The //export directive is needed to include the function in the generated header file, the argument is *C.char rather than string or GoString. The C++ code uses the header generated by cgo, and there has to be a const-removing cast from the static string (because go doesn't have C-like const).
libmylib.go
package main
import "C"
import (
"fmt"
)
//export say
func say(text *C.char) {
fmt.Println(C.GoString(text))
}
func main() {}
main.cpp
#include "libmylib.h"
int main(void) {
say(const_cast<char*>("hello world"));
return 0;
}
commands
This compiles to go file, generating libmylib.so and libmylib.h in the current directory.
go build -o libmylib.so -buildmode=c-shared libmylib.go
The compiles the C++ program, linking it to the shared library above:
g++ -L. main.cpp -lmylib -o hello_program
To run the program, LD_LIBRARY_PATH needs to be set to the current directory. That would be different if program was installed and the shared library put in a sensible place.
LD_LIBRARY_PATH=. ./hello_program

g++ -L/path/to/lib/ -lmylib main.cpp -o test
is probably wrong. Read the invoking GCC chapter of the GCC documentation. Order of arguments to g++ matters a lot.
Also, test(1) could be some existing executable. I recommend to use some other name.
So consider compiling with
g++ -Wall -g -O main.cpp -L/path/to/lib/ -lmylib -o my-test-program
You probably want debugging information (-g), warnings (-Wall) and some optimization (-O)
You did comment
I need to use some functions from a Go file in my C ++ project.
This is curious. I assume your operating system is some Linux. Then, can't you just use inter-process communication facilities between a process running a Go program and another process running your C++ program? Consider perhaps using JSONRPC or HTTP between them. There exist several open source libraries in Go and in C++ to help you.
PS. As I commented, calling C++ code from a Go program could be much simpler. Of course you do need to read the Go documentation and the blog about cgo and probably the C++ dlopen minihowto and some C++ reference.

Related

is there any way that I can add my own custom c/c++ header file to where the standard header functions come from so that I can use them at any time [duplicate]

I am having trouble installing a dependency for a program that itself depends on pcre.h. I have this installed to /opt/local/include, but the C compiler does not see it and thus gives me:
error: pcre.h: No such file or directory
I have confirmed this by writing a hello world program that tries to include it:
#include <pcre.h>
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
return 0;
}
This also gives the error unless I specify the path as </opt/local/include/pcre.h>.
I would like the C compiler to find this by default but I do not know where this is configured. Tab completion hasn't revealed any HEADER_PATH environment variables and I cannot find anything like it that isn't specific to XCode. I am, however, using Mac OSX Snow Leopard on the off chance that makes a difference.
Use -I /opt/local/include on the command line or C_INCLUDE_PATH=/opt/local/include in the environment.
Use the pcre-config utility to get the right flags:
$ pcre-config --libs --cflags
-L/opt/local/lib -lpcre
-I/opt/local/include
If you're compiling via the command line,
$ gcc -Wall -g `pcre-config --libs --cflags` main.c

Call cuda library on windows

I am trying to use cuda to parallelize a Go project.
I've read Golang calling CUDA library many times.
I'm trying to do the same thing on Windows and having trouble. (I'm assuming this OP was using Linux because of the .so files)
I have successfully compiled/run the following test program involving no cuda code to make sure I have CGO working correctly.
test.cpp
extern "C"{
int testfunc(){
return 1000;
}
}
compiled with g++
g++ test.cpp -o test.dll --shared
callC.go
package main
//int testfunc();
//#cgo LDFLAGS: -L. -ltest
import "C"
import "fmt"
func main() {
fmt.Println(C.testfunc())
}
prints 1000 - great!
now I try the same thing with nvcc and I get an error from ld that theres an undefined reference to testfunc.
test.cu
extern "C"
{
int testfunc()
{
return 1 + 1;
}
}
compiled with
nvcc test.cu -o testcuda.dll --shared --compiler-options -fPIC ... I always get:
cl : Command line warning D9002 : ignoring unknown option '-fPIC'
cl : Command line warning D9002 : ignoring unknown option '-fPIC'
cl : Command line warning D9002 : ignoring unknown option '-fPIC'
Creating library testcuda.lib and object testcuda.exp
callCudaC.go
package main
//int testfunc();
//#cgo LDFLAGS: -L. -ltestcuda
//#cgo LDFLAGS: -LC:\temppath\CUDA\v11.2\ -lcudart
import "C"
import "fmt"
func main() {
fmt.Println(C.testfunc())
}
running this go code results in
C:\Users\MICHAE~1\AppData\Local\Temp\go-build045526290\b001\_x002.o: In function `_cgo_701f531a6502_Cfunc_testfunc': /tmp/go-build/cgo-gcc-prolog:52: undefined reference to `testfunc' collect2.exe: error: ld returned 1 exit status
you'll note that my "cuda" code doesn't involve any cuda, just one exported function and that I tried moving the cuda installation to a simpler path so I could actually pass it as a directory to the linker - I'm not sure if it's even needed since there is no use of cuda syntax etc.
Would be appreciative of debugging tips or hints if anyone has seen this before.
Thanks to the direction from #talonmies comments I found that at least in simple cases I could call the dlls created by cl.exe and nvcc.exe from cgo by defining a header file that looks like this:
#ifdef __cplusplus
extern "C" { // only need to export C interface if
// used by C++ source code
#endif
__declspec(dllexport) int testfunc();
#ifdef __cplusplus
}
#endif
this code was created referencing these two MSDN articles:
https://learn.microsoft.com/en-us/cpp/build/exporting-cpp-functions-for-use-in-c-language-executables?view=msvc-160
https://learn.microsoft.com/en-us/cpp/build/exporting-c-functions-for-use-in-c-or-cpp-language-executables?view=msvc-160

Compiling several source (main and headers) files and linking them in ROOT CINT?

Let me first set the context, it is CERN's ROOT and CINT and ACLiC etc.
Suppose I have a main macro named macro.cpp and two headers h1.cpp (contains the definition of a function) and h1.h containing the declaration of the function defined in h1.cpp similarly I have h2.cpp and h2.h. The main program macro.cpp calls those functions inside h1 and h2. I was successful compiling the source files using:
root [0] .L h1.cpp+
root [1] .L h2.cpp+
root [2] .L macro.cpp+
which generated three .so files macro_cpp.so, h1_cpp.so and h2_cpp.so. I want to know what to do with them ? How do I link them so that I have something like a "macro.out" or something like that (a single executable file of some kind) which I can execute (although I don't know how !) and achieve whatever I wished to achieve with the macro.
Note: If I just load all the files using .L file_name.cpp etc and just execute the main macro using .x macro.cpp then everything works fine and I have results, but this is not what I want ! I want to compile like we do in usual g++ and by the way in every forum everyone keeps advising on compiling using .L file_name.cpp+ or ++ .. I would really like to know the whole story. Because nobody seems to explain beyond .L file_name.cpp+ .. what next ? What to do with the .so etc.
I am a beginner, I will really appreciate a simple and step by step answer and explanation.
Thanks.
Edit-1: I am working with:
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Edit-2: ROOT related information:
ROOT 5.34/36 (v5-34-36#v5-34-36, dic 07 2016, 23:31:51 on linuxx8664gcc)
CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
If you want to compile and link you can use a standard compiler instead of Cint/Aclic.
For example, assuming you are working on a *nix platform, you can use the example files below:
h1.h
int add_one(int a);
h1.cpp
#include "h1.h"
int add_one(int a)
{
return a+1;
}
h2.h
#include <TLorentzVector.h>
TLorentzVector multiply_by_two(const TLorentzVector v);
h2.cpp
#include "h2.h"
TLorentzVector multiply_by_two(const TLorentzVector v)
{
return 2.0*v;
}
macro.cpp
#include "h1.h"
#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
return 0;
}
Then you can compile with
g++ -c -g -Wall `root-config --cflags` h1.cpp
g++ -c -g -Wall `root-config --cflags` h2.cpp
g++ -c -g -Wall `root-config --cflags` macro.cpp
and link with
g++ `root-config --glibs` h1.o h2.o macro.o
The executable will be a.out:
$ ./a.out
calling add_one on 0: 1
calling multiply_by_two on 1: 2
You can put these g++ commands in a script or, when you start having several files and directories, you can write your make file (or cmake). For this last step, see for example the tutorial here
http://www-pnp.physics.ox.ac.uk/~brisbane/Teaching/Makefiles/Tutorial_1_Makefiles_and_ROOT.pdf
Note 1: one advantage of using g++ is that you will get clear error messages when something doesn't compile. The error messages from Cint can
be difficult to understand--although this is very much improved in root 6 with Cling.
Note 2: another advantage of using a standard compiler is that you will be able to easily link your main executable against libraries other than root.
This answer is based mostly on the answer by user2148414, but if one follows the answer will notice that there were some issues with the method of linking the source (*.cpp) files. My answer also addresses another important object called a TApplication that will play a crucial role in such applications involving root libraries. The following linking step:
g++ `root-config --glibs` h1.o h2.o macro.o
will likely show a lot of errors complaining about the root objects like TWhatever (in user2148414's answer TLorentzVector will show problems). In the comments to that answer one can find the discussion on including various physics libraries that can solve the problem but without discussing that (and I am not comfortable either :) ) let me write down the command that solves everthing.
This procedure is a one-liner, that is no need to compile individual files, create *.cpp files and *.h files as discussed in that answer then compile and link and create a single executable named "someExecutable" using:
g++ macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
or better (and one should do it)
g++ -Wall -Wextra -Werror -pedantic -std=c++14 macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
This will solve my original answer but for completeness I would like to add a few more things.
TApplication
My original motivation was to create an application that talks to "ROOT" but I didn't want to work with the ROOT shell, CINT, ACLiC etc and wanted to work entirely with g++. user2148414's and my answer will solve the part of creating an application but the application will not serve any purpose, it will run, create histograms draw them and do all the stuff but all the canvases will close in the end when the code reaches "return 0;". To keep the canvases open we will need "TApplication". So the consider the main of user2148414's answer, I am going include just two more lines and include two arguments to the main:
macro.cpp
#include "h1.h"
#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) //introduced arguments to main
{
// here I introduce TApplication
TApplication* SomeApp = new TApplication("SomeApp",&argc, argv);
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
//and just before returning 0
SomeApp->Run();
return 0;
}

Compiling a C program without Main [duplicate]

This question already has answers here:
How to compile C source code without a main function?
(6 answers)
Closed 7 years ago.
I have a simple C program I have to make (Which can't use a main function).
As such:
test.c
#include <stdio.h>
int getUserID(int id);
int getUserID(int id) {
return 0;
}
Where my current function does nothing as of now:
However, I'm trying to compile this through a makefile, as such:
all:
gcc test.c
Which didn't work because I didn't have a main so then I added the -c command within it.
all:
gcc -c test.c
Which now compiles with make, but gives me an object file (but without a working executable), the executable I get when I try to run it: i.e ./test tells me permission denied
Any help would be greatly appreciated.
You cannot have a C++ or C program without a main (without evil, non-standard hacks at least). You can build a library without a main, but not a standalone executable.
For standalone applications, the main function is crucial because it defines where to start execution.
You can create an image where "main" is not the entry point.
Here is one such way (using gcc on a RHEL6 system):
$ cat sample.c
#include <stdio.h>
#include <unistd.h>
int notmain ( void ) {
printf("hello, world\n");
exit(0);
}
$ cc -ffreestanding -c sample.c
$ ld -enotmain -o sample sample.o -I/lib64/ld-linux-x86-64.so.2 -lc
$ ./sample
hello, world
And, BTW, this is not an "evil, non-standard hack" -- the C Standard defines two execution environments: (1) "hosted", which is the one most people are familiar with, and (2) "freestanding", which is typically some sort of embedded system (a toaster or whatnot).
You can separately compile this c file into an object file, but it will need to be linked with another object file containing the main function to become an executable program.
If you are not allowed to have a main function in this file, there must be another file you are expected to link with it.

Link dynamic shared library in Linux - Undefined reference to function

I know there are many questions related to shared libraries on Linux but maybe because I'm tired of having a hard day trying to create a simple dynamic library on Linux (on Windows it would have taken less than 10 minutes) I can't find what happens in this case.
So, I am trying to create a library to be linked at build-time and used at run-time (not a static library, not a library to be embedded into the executable, in other words). For now it contains a simple function. These are my files:
1.
// gugulibrary.cpp
// This is where my function is doing its job
#include "gugulibrary.h"
namespace GuGu {
void SayHello() {
puts("Hello!");
}
}
2.
// gugulibrary.h
// This is where I declare my shared functions
#include <stdio.h>
namespace Gugu {
void SayHello();
}
3.
// guguapp.cpp
// This is the executable using the library
#include "gugulibrary.h"
int main() {
GuGu::SayHello();
return 0;
}
This is how I try to build my project (and I think this is what is wrong):
gcc -Wall -s -O2 -fPIC -c gugulibrary.cpp -o gugulibrary.o
ld -shared -o bin/libGugu.so gugulibrary.o
gcc -Wall -s -O2 guguapp.cpp -o bin/GuGu -ldl
export LD_LIBRARY_PATH=bin
This is saved as a .sh file which I click and execute in a terminal. The error I get when trying to link the library is this:
/tmp/ccG05CQD.o: In function `main':
guguapp.cpp:(.text.startup+0x7): undefined reference to `SayHello'
collect2: ld returned 1 exit status
And this is where I am lost. I want the library to sit in the same folder as the executable for now and maybe I need some symbols/definitions file or something, which I don't know how to create.
Thanks for your help!
In your C++ file, GuGu::SayHello is declared as a C++ symbol. In your header, you are wrapping it in an extern "C" block. This is actually undefined, as you aren't allowed to use C++ syntax (namespace) in that context. But my guess is that what the compiler is doing is ignoring the namespace and generating a C symbol name of "SayHello". Obviously such a function was never defined by your library. Take out the extern "C" bits, because your API as defined cannot be used from C anyway.
You are inconsistent with your GuGu, there are also Gugu's running around, this needs to be made consistent, then it works (At least on my computer are some Gugu's now)