c++ access extern in cgo - c++

I am using this:
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
void foo();
#ifdef __cplusplus
}
#endif
//foo.cc
void foo() {
cout << "Hello World" << endl;
}
to link between my cgo process and c++ process. I want to access a golang function from my c++ function foo. My go looks like:
// #include "foo.h"
import "C"
func golangPart() {
//do stuff in go
}
func main() {
C.foo()
}
I want to access golangPart() from the c++. I have tried this:
//foo.h
void golangPart();
#ifdef __cplusplus
extern "C" {
#endif
void foo();
#ifdef __cplusplus
}
#endif
//foo.cc
void foo() {
golangPart();
}
But it gave me this error:
./foo.cc:42: undefined reference to `golangPart()'
collect2.exe: error: ld returned 1 exit status

Related

"multiple definition of" while variable is not defined anywhere else in the scope

I have these three source files:
test.h
#ifndef __TESTH
#define __TESTH
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef struct {
uint8_t value;
} my_struct;
EXTERNC void initialise();
EXTERNC void load(my_struct**);
#endif
test.cpp:
#include <cstdint>
#include "test.h"
my_struct test;
void initialise() {
test.value = 200;
}
void load(my_struct** struct_ptr) {
*struct_ptr = &test;
}
main.cpp:
#include <cstdint>
#include <iostream>
#include "test.h"
my_struct *test;
int main() {
initialise();
load(&test);
while (true) {
std::cout << test->value << std::endl;
}
}
When I compile it, the linker gives me an error telling me that test has been defined multiple times (first defined in test.cpp).
Why? To me it seems like it doesn't leave the scope of test.cpp.
And when I remove the definition of test in main.cpp, it gives me an undefined error!
Thank you for taking the time out of your day to help me.
I think you would need to scope test.cpp's test variable to that file only, assuming your test pointer in main.cpp is different than test in test.cpp
namespace {
my_struct test;
}
See here

CGO, pass a struct from go to c++

I am experimenting with cgo, and wanted to use c++ with cgo. I found this post about doing it. If I have a c++ struct named Foo and a go struct named Foo, I want to pass the go Foo to c++. I tried doing this:
//bind.h
#ifdef __cplusplus
extern "C" {
#endif
#include "structs.hpp"
void bindCgo(Foo bar);
#ifdef __cplusplus
}
#endif
//structs.hpp
#ifndef STRUCTS_HPP_
#define STRUCTS_HPP_
typedef struct Foo {
#ifdef __cplusplus
std::string str;
#endif
}
#endif
//bind.cc
#include "structs.hpp"
using namespace std;
void bindCgo(Foo bar) {
cout << bar.str << endl; //this gives "sΘ\"
}
//main.go
import "unsafe"
// #cgo CFLAGS: -std=c99
// #include "bind.h"
import "C"
type Foo struct {
str string
}
func main() {
bar := Foo{""};
C.bindCgo(((*C.Foo)(unsafe.Pointer(&bar))))
}
Now when I run this program, it gives me sΘ\. Is this normal, and how can I fix this?
I also have maps and vectors in my struct so using char* will not work

can I use extern "C" { headerfile of c }

Instead of writing each function in " extern "C" {} ", can I write entire header file inside that block.
extern "C"
{
#include "myCfile.h"
}
I have tried this but Its not working at all, why it is not working ?
if we have to use 100 C functions in a c++ project, do we need provide all the functions in a
extern block, is there any other simple way ?
Ex:
extern "C"
{
void fun1();
void fun2();
void fun3();
void fun4();
void fun5();
.
.
.
.
fun100();
}
Is there any other simple way, like extern "C" { myCfunctions.h } ???
#include simply includes the specified header at the location of the #include. Whether it's valid depends on what "myCfile.h" contains. In particular, including any standard library headers in such a context is not valid, and may well break on commonly used implementations.
The usual way to handle this is to make the header itself safe to use from C++. A C-only header might contain
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#endif
Adapting this to make it safe to use from C++:
#ifndef H_MYCFILE
#define H_MYCFILE
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void mycfunc1(void);
void mycfunc2(int i);
void mycfunc3(size_t s);
#ifdef __cplusplus
}
#endif
#endif
With such a header, you wouldn't be able to safely put the entire header in an extern "C" block. However, that header itself can make sure not to put #include <stddef.h> in an extern "C" block, but still to put all function declarations in a single extern "C" block, avoiding having to repeat it for each one.
You are doing something wrong.
Because
extern "C" { myCfunctions.h }
should work. See below sample program.
Lets go by example code.
ctest1.c
#include<stdio.h>
void ctest1(int *i)
{
printf("This is from ctest1\n"); // output of this is missing
*i=15;
return;
}
ctest2.c
#include<stdio.h>
void ctest2(int *i)
{
printf("This is from ctest2\n"); // output of this is missing
*i=100;
return;
}
ctest.h
void ctest1(int *);
void ctest2(int *);
Now lets make c library from that
gcc -Wall -c ctest1.c ctest2.c
ar -cvq libctest.a ctest1.o ctest2.o
Now lets make cpp based file which will use this c apis
prog.cpp
#include <iostream>
extern "C" {
#include"ctest.h"
}
using namespace std;
int main()
{
int x;
ctest1(&x);
std::cout << "Value is" << x;
ctest2(&x);
std::cout << "Value is" << x;
}
Now lets compile this c++ program with C library
g++ prog.cpp libctest.a
Output is :
Value is15Value is100

extern keyword in C on more functions

I would like to include one header file in both C and C++, and I have a function defined in C code and few functions defined in external library.
#if defined(__cplusplus)
extern "C" {
#endif
void func0();
#if !defined(__cplusplus)
extern {
#endif
void func1();
int func2(int);
} /* extern */
This code produces compilation error when compiled from C source file
error C2059: syntax error : '{'
Is it possible to fix syntax error directly or I have to use some macros?
EXTERNCPP void func0();
EXTERNC void func1();
EXTERNC int func2(int);
Edit 1:
I do not ask about
Effects of the extern keyword on C functions, I just ask if it is possible to fix syntax in easy way. If it is not possible, i could still remove it completely for C part
Edit 2:
To clarify what I want to get. If header is included
from C++:
extern "C" void func0();
extern "C" void func1();
extern "C" int func2(int);
from C:
void func0();
extern void func1();
extern int func2(int);
extern { is not needed.You need to remove it:-
#if defined(__cplusplus)
extern "C" {
#endif
void func0();
#if !defined(__cplusplus)
#endif
void func1();
int func2(int);
#if defined(__cplusplus)
}
#endif
You can simply omit the extern { line when compiling as a C header.
#if defined(__cplusplus)
extern "C" {
void func0();
#endif
#if !defined(__cplusplus)
void func1();
int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
* [EDIT] answering your last edit:
void func0(); /* included in both versions */
#if defined(__cplusplus)
extern "C" {
void func1();
int func2(int);
#endif
#if !defined(__cplusplus)
extern void func1();
extern int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
If you want to use func0 as extern in C:
#if defined(__cplusplus)
extern "C" {
void func0();
void func1();
int func2(int);
#endif
/* C block */
#if !defined(__cplusplus)
extern void func0();
extern void func1();
extern int func2(int);
#endif
#if defined(__cplusplus)
}
#endif
If you don't want to use it at all (from C) remove it from the C block

C code compiles in Windows, gives compilation error on Linux

Contents of somefile.h:
#ifndef __SOMEFILE_H
#define __SOMEFILE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _table_t
{
void (*somefunction1)();
void (*somefunction2)(int a);
void (*somefunction3)(int a, int *b);
}table_t;
void doSomething1();
void doSomething2();
#ifdef __cplusplus
} // error at this line: expected constructor, destructor, or type conversion before '(' token
#endif
#endif
Shown above is the code snippet and the error I get when I compile my code on Linux. The same code compiles fine on Windows with no complaints.
About the source file:
all.h is a header file which includes:
#include "header1.h"
#include "header2.h"
#include "header3.h"
#include "somefile.h"
Here is the content of somefile.c
#include "all.h"
#include "header4.h"
jumptable_t jumptable_a =
{
a_function1();
a_function2(int a);
a_function3(int a, int *b);
}
//more code
void function1()
{
a_function1();
}
void function2(int a)
{
a_function2(a);
}
void function3(int a, int *b)
{
a_function3(a, b);
}
void doSomething1()
{
}
void doSomething2()
{
}
Macro with leading double underscores is illegal. You need to change your include guard.
You need a ; after the } of jumptable_a. And use commas instead of semicolons in the initializer of jumptable_a.
The braces make it look like a somethink function-like, but it's not.
Also, in somefile.h the struct is called table_t, but in somefile.c you are using jumptable_t, which I assume is an error introduced when writing the post here.