Cgo pass a string to C file - go

I am using cgo and saw this post about running c++ from go:
I want to use [this function] in Go. I'll use the C interface
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* Foo;
Foo FooInit(void);
void FooFree(Foo);
void FooBar(Foo);
#ifdef __cplusplus
}
#endif
I did this, but how can I pass a string as an argument to the C++ function? I tried to pass a rune[] but it did not work.

This is the Go code:
// GetFileSizeC wrapper method for retrieve byte lenght of a file
func GetFileSizeC(filename string) int64 {
// Cast a string to a 'C string'
fname := C.CString(filename)
defer C.free(unsafe.Pointer(fname))
// get the file size of the file
size := C.get_file_size(fname)
return int64(size)
}
From C
long get_file_size(char *filename) {
long fsize = 0;
FILE *fp;
fp = fopen(filename, "r");
if (fp) {
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fclose(fp);
}
return fsize;
}
Remember that you need to add the headers library that you need before the import in the Go file:
package utils
// #cgo CFLAGS: -g -Wall
// #include <stdio.h> |
// #include <stdlib.h> | -> these are the necessary system header
// #include <string.h> |
// #include "cutils.h" <-- this is a custom header file
import "C"
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
....
)
This is an old project that you can use for future working example:
https://github.com/alessiosavi/GoUtils

Related

undefined reference to error only for certain functions

I have a library and a C interface built for it.
My program compiles just fine with versionString() but not with loadConfig(). How is that possible?
walker.h :
#ifndef WFE_C_H
#define WFE_C_H
#ifdef __cplusplus
extern "C" {
#endif
const char* versionString();
void* loadConfig(const char *filePath, char* errorMessageBuffer, int bufferLen);
#ifdef __cplusplus
}
#endif
#endif
Working version:
package main
/*
#cgo CFLAGS: -Isrc/walker
#cgo LDFLAGS: -L${SRCDIR}/lib -lwalker
#include "walker.h"
*/
import (
"C"
)
func main() {
p := C.versionString()
version := C.GoString(p)
fmt.Println(version)
}
// output: v1.94
Not working version:
package main
/*
#cgo CFLAGS: -Isrc/walker
#cgo LDFLAGS: -L${SRCDIR}/lib -lwalker
#include "walker.h"
*/
import (
"C"
)
func main() {
errorMessageBuffer := C.CString("")
pathPtr := C.CString("/src/vali/config")
bufferLen := C.int(len(4000))
C.loadConfig(pathPtr, errorMessageBuffer, bufferLen)
}
Traceback:
/tmp/go-build056292810/github.com/testong/vali/_obj/main.cgo2.o: In
function `_cgo_b2bd1c9e3dda_Cfunc_loadConfig':
/tmp/go-build/github.com/testong/vali/_obj/cgo-gcc-prolog:43: undefined
reference to `loadConfig'
collect2: error: ld returned 1 exit status
In walker.h , the export function is
void* loadConfig(const char *filePath, char* errorMessageBuffer, int bufferLen);
And you used C.loadConfigDirectory(pathPtr, errorMessageBuffer, bufferLen).
The function loadConfigDirectory is not defined.
Maybe it is a typo?
Working version works because versionString is already defined.

How to Link Golang package to an existing C project (Using Go from C) on windows x86-64

How to use Golang Generated libgolang.a from C code to build C executable: test.exe:
these commands makes executable binary 'test' in Ubuntu x86-64 and works fine (but not in Windows x86-64):
go build -buildmode c-archive -o libgolang.a
gcc -o test _main.c libgolang.a -lpthread
with:
this is main.go file:
package main
import "C"
import "fmt"
//export Add
func Add(a, b uint64) uint64 {
return a + b
}
func main() {
fmt.Println("Hi")
}
and this is _main.c file:
#include <stdio.h>
#include <stdint.h>
#include "libgolang.h"
int main()
{
uint64_t a=10;
uint64_t b=20;
uint64_t c=Add(a,b);
printf("%ld\n",c);
return 0;
}
in Windows this command:
go build -buildmode c-archive -o libgolang.a
works fine and generates libgolang.a and libgolang.h files. libgolang.h:
/* Created by "go tool cgo" - DO NOT EDIT. */
/* package github.com/ARamazani/go/DLL */
/* Start of preamble from import "C" comments. */
/* End of preamble from import "C" comments. */
/* Start of boilerplate cgo prologue. */
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern GoUint64 Add(GoUint64 p0, GoUint64 p1);
#ifdef __cplusplus
}
#endif
but this command:
gcc -o test _main.c libgolang.a -lpthread
output:
libgolang.a(go.o):(.data+0x2150): undefined reference to `NtWaitForSingleObject'
libgolang.a(go.o):(.data+0x21b8): undefined reference to `WSAGetOverlappedResult'
libgolang.a(go.o):(.data+0x21d8): undefined reference to `timeBeginPeriod'
collect2.exe: error: ld returned 1 exit status
go version go1.7rc3 windows/amd64
I want to use this libgolang.a from C code to build C executable: test.exe
any workaround?
some useful links:
http://blog.ralch.com/tutorial/golang-sharing-libraries/
Using Go code in an existing C project
Using Go on existing C project
Finally found at least one way:
using this file main.go:
package main
import "C"
import "fmt"
//export Add
func Add(a, b uint64) uint64 {
return a + b
}
func main() {
fmt.Println("Hi")
}
run this command:
go build -buildmode c-archive -o libgolang.a
to generate libgolang.a and libgolang.h
then using _main.c:
#include <stdio.h>
#include <stdint.h>
#include "libgolang.h"
int main()
{
uint64_t a=10;
uint64_t b=20;
uint64_t c=Add(a,b);
printf("%ld\n",c);
return 0;
}
this is the answer (this works for me):
gcc -o test _main.c libgolang.a -lWinMM -lntdll -lWS2_32
that test.exe created.
run:
test.exe
output:
30
The Microsoft Windows always trick us!
But for production code my suggestion is use the optimization compile commands below:
go build -ldflags "-s -w" -buildmode c-archive -o libgolang.a
The parameter -ldflags "-s -w", will reduze the final file size.
The "libgolang.a" shrink from 4.295.562 to 1.994.554.
And the "test.exe" shrink from 3.430.485 to 1.715.561.
I guess this is a desired behavior!

Unable to get the stack trace with a corefile from a cgo routine when using golang

I am using Golang and cgo. When my C code raises an assert(), I am unable to see the stack trace of the C code when using cgo.
Instead, I see the stack trace of the golang runtime that caught the assert.
Here is an example of my C code
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>
void fn2(char *arg)
{
int stackvar2 = 256;
printf("Argument %s\n", arg);
assert(1 == 2);
}
void fn1(int arg)
{
int stackvar3 = 512;
char var[256];
strcpy(var, "deadbeef");
fn2(var);
}
void *thread(void *arg)
{
printf("Hello from the thread... going in for an assert\n");
fn1(1092);
return NULL;
}
void hello_world(char *str)
{
pthread_t tid;
printf("Hello World from C and here the str is from Go: %s\n", str);
pthread_create(&tid, NULL, thread, NULL);
sleep(100000);
}
Here is my Go code
package main
/*
extern void hello_world(char *str);
#cgo LDFLAGS: -L. -lhello
#cgo CFLAGS: -g3
*/
import "C"
import (
_ "fmt"
)
func main() {
str := "From Golang"
cStr := C.CString(str)
C.hello_world(cStr)
select {}
}
And here is my Makefile
all:
gcc -g3 -O0 -c hello.c
ar cru libhello.a hello.o
go build hello.go
clean:
rm -f *.o hello
Besides the obvious check of ulimit -c, run the go program with GOTRACEBACK=crash. This will print out more information, and allow the program to exit with SIGABRT to trigger a core dump.
Actually I need to add this to my go code: signal.Ignore(syscall.SIGABRT). This allows me to see the stack trace of the C code that crashed.

how to compile Cuda source with Go language's cgo?

I wrote a simple program in cuda-c and it works on eclipse nsight. This is source code:
#include <iostream>
#include <stdio.h>
__global__ void add( int a,int b, int *c){
*c = a + b;
}
int main(void){
int c;
int *dev_c;
cudaMalloc((void**)&dev_c, sizeof(int));
add <<<1,1>>>(2,7,dev_c);
cudaMemcpy(&c, dev_c, sizeof(int),cudaMemcpyDeviceToHost);
printf("\n2+7= %d\n",c);
cudaFree(dev_c);
return 0;
}
Now I'm trying to use this code with Go language with cgo!!!
So I wrote this new code:
package main
//#include "/usr/local/cuda-7.0/include/cuda.h"
//#include "/usr/local/cuda-7.0/include/cuda_runtime.h"
//#cgo LDFLAGS: -lcuda
//#cgo LDFLAGS: -lcurand
////default location:
//#cgo LDFLAGS: -L/usr/local/cuda-7.0/lib64 -L/usr/local/cuda-7.0/lib
//#cgo CFLAGS: -I/usr/local/cuda-7.0/include/
//
//
//
//
//
//
//
//
//
//
/*
#include <stdio.h>
__global__ void add( int a,int b, int *c){
*c = a + b;
}
int esegui_somma(void){
int c;
int *dev_c;
cudaMalloc((void**)&dev_c, sizeof(int));
add <<<1,1>>> (2,7,dev_c);
cudaMemcpy(&c, dev_c, sizeof(int),cudaMemcpyDeviceToHost);
cudaFree(dev_c);
return c;
}
*/
import "C"
import "fmt"
func main(){
fmt.Printf("il risultato รจ %d",C.esegui_somma)
}
But it doesn't work!!
I read this error message:
cgo_cudabyexample_1/main.go:34:8: error: expected expression before '<' token
add <<<1,1>>> (2,7,dev_c);
^
I think that I must to set nvcc cuda compiler for cgo instead of gcc.
How can I do it? Can I change CC environment variable?
best regards
I finally figured out how to do this. Thing biggest problem is that nvccdoes not follow gcc standard flags and unlike clang it won't silently ignore them. cgo triggers the problem by adding a bunch of flags not explicitly specified by the user.
To make it all work, you'll need to separate out your device code and the functions that directly call it into separate files and compile/package them directly using nvcc into a shared library (.so). Then you'll use cgo to link this shared library using whatever default linker you have on your system. The only thing you'll have to add is -lcudart to your LDFLAGS (linker flags) to link the CUDA runtime.

Flex- define main function in the code part

I'm a nooby to flex.
I have a simple h.w- to read the input and to print some words acording to the input.
I'm using an hash table that is weitten in another c & h files.
herer is my code:
%{
#include <stdio.h>
#include "hashtbl.h"
#include "hashtbl.c"
void add_define( char * str);
HASHTBL *my_table;
char* get_define(char * str);
%}
...
...
%%
...
...
%%
void main()
{
my_table = hashtbl_create(100, NULL);
yylex();
hashtbl_destroy(my_table);
}
void add_define( char * str)
{
...
...
}
char* get_define(char * str)
{
...
...
}
when I try to compile it with- gcc -ll lex.yy.c
I get an error regarding the main function-
"multiple definition of main ....
I know I can compile it with - gcc lex.yy.c -lfl
but I cannot use it
any help?
I had to delete the main function and use other ways for what I wanted to do

Resources