I try to call a C function pointer as a callback from a Go function but get a linker error I don't understand.
package main
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
//export IntIntCallback
func IntIntCallback(a, b C.int, cb C.int_int) {
C.bridge_int_int(a, b, cb)
}
func main() {
// Noop, required to make CGO happy: `-buildmode=c-*` requires exactly one
// main package, which in turn needs a `main` function`.
}
The error is:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/../../../../i686-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `bridge_int_int':
./test.go:6: multiple definition of `bridge_int_int'; $WORK\b001\_x001.o:/tmp/test.go:6: first defined here
collect2.exe: error: ld returned 1 exit status
I don't understand where this multiple definition problem comes from.
Problem solved. See: https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go
Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations. If a file contains both definitions and declarations, then the two output files will produce duplicate symbols and the linker will fail. To avoid this, definitions must be placed in preambles in other files, or in C source files.
Moving the following code into a separate .go file:
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
and changing it to
/*
typedef void (*int_int)(int, int);
extern bridge_int_int(int a, int b, int_int f);
}
*/
import "C"
...
in the original file solved the problem
Related
For debugging reasons i created the following code example: There is a function a() which is called by the function b(). I want to know the name of the function which calls a(). So i created the code below which is working fine:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
uint8_t a(uint8_t k)
{
printf("function: a\n");
return k;
}
uint8_t a_debug( uint8_t j, char const *caller_name)
{
uint8_t rtv;
printf("a was called by %s\n", caller_name);
rtv = a(j);
return rtv;
}
#define a(x) a_debug(x,__func__)
void b()
{
uint8_t asdf;
asdf = a(5);
printf("asdf = %u", asdf);
}
int main(int argc, char **argv)
{
b();
return 0;
}
In a bigger software project with several c- and h-files I pasted the code
uint8_t a_debug( uint8_t j, char const *caller_name)
{
uint8_t rtv;
printf("a was called by %s\n", caller_name);
rtv = a(j);
return rtv;
}
#define a(x) a_debug(x,__func__)
right below the function a() to debug the function a(). I can build and execute the software-project but the function a_debug() is never entered. Instead of the function a() is directly executed. In which file or exactly where do I have to define the preprocessor directive #define a(x) a_debug(x,__func__) so that the compiler will displace a() with a_debug() function?
Preprocessor directives operate only in the translation unit where they appear.
A translation unit is the source file being compiled, including all the files it includes. To use a preprocessor macro, it must be defined in the translation unit. The way this is usually done is that a source file containing some functions named foo or related to some category or idea foo are defined in a file named foo.c, and declarations for those functions are put in a file named foo.h. The header file foo.h should provide whatever preprocessor macros, declarations, and other things are needed to use the facilities provided by foo.c.
To start, you can put your new function a_debug in the source file that contains a. Also, you can simplify it; there is no need for the variable rtv:
uint8_t a_debug(uint8_t j, char const *caller_name)
{
printf("a was called by %s.\n", caller_name);
return a(j);
}
Then, in the header file that declares a, you need to add two things. First, a declaration for a_debug:
uint8_t a_debug(uint8_t, char const *);
Second, a definition for the macro a:
#define a(x) (a_debug((x), __func__))
However, this is going to cause a problem. The source file defining a should include its own header file. (One reason for this is to allow the compiler to check for errors such as function declarations not matching function definitions.) But when it includes the header file, that will define the a macro, and then, when the function a is defined, the definition will be altered by the macro replacement, and the compiler will complain. One way around this is to put #undef a in the source file that defines a, after it includes its header file.
Also, since a_debug is so simple, you can define it as a static inline function in the header. Instead of putting the definition shown above in the source file and its declaration in the header file, put this in the header file:
static inline uint8_t a_debug(uint8_t j, char const *caller_name)
{
printf("a was called by %s.\n", caller_name);
return a(j);
}
I have a project that includes three files in codeblocks:
main.c :
#include <stdio.h>
#include <conio.h>
int global = 10;
void f1(int);
void f1_1(int);
void f2(void);
int main()
{
int x = 5;
printf("inside main file");
getch();
f1(x);
f2();
getch();
return 0;
}
file1.c :
#include <stdio.h>
#include <conio.h>
void f1(int x)
{
printf("\ninside file1 >> f1 and x = %i", x);
getch();
f1_1(x);
}
void f1_1(int x)
{
printf("\ninside file1 >> f1 >> f1_1 and x = %i", x);
getch();
}
file2.c :
#include <stdio.h>
#include <conio.h>
extern int global;
void f2()
{
printf("\ninside file2 >> f2 function , global var = %i", global);
getch();
}
When I compiled it, I got these warnings:
c|8|warning: implicit declaration of function 'f1_1'; did you mean 'f1'? [-Wimplicit-function-declaration]
c|11|warning: conflicting types for 'f1_1'
What should I do for this?
void f1(int);
void f1_1(int);
void f2(void);
Should be:
extern void f1(int);
extern void f1_1(int);
extern void f2(void);
Or, as #kiranBiradar points out, you can declare them in header files
file1.h
#pragma once
extern void f1(int);
extern void f1_1(int);
file2.h
#pragma once
extern void f2(void);
Note the use of the extern keyword. When you forward declare a function in a file as void f(void), the symbol 'f' is public, meaning other compilation units can reference it. When you declare it as extern void f(void), then the compiler doesn't expect the function to be defined in that compilation unit and leaves it up to the linker to find that symbol.
This is the perfect time to learn about the important concept of translation units.
Each single source file, with all included header file, forms a single translation unit. Each translation unit is separate and distinct and compiled stand-alone without any knowledge of other translation units.
That means symbols declared in e.g. the main.c source file will not be known in the file1.c source file.
When you compile file1.c the compiler simply doesn't know about the f1_1 function declaration you have in the main.c source file, so you get a warning about that fact.
To solve your problem, you need to declare the f1_1 function in the file1.c file. Either by adding a forward declaration (like the one you have in main.c), or moving the whole function definition (implementation) of f1_1 above the f1 function.
Or you could create a single header file which contains all the declarations needed (for the f1, f1_1, f2 function, plus the global external variable declaration), and include this single header file in all your source files. This solution works best if you have multiple symbols (functions, variables, etc.) that are used in multiple translation units.
My personal recommendation is this: Since the f1_1 function is only used internally inside the file1.c source file, move its definition above f1, and make it static. Then remove its declaration from the main.c source file.
Regarding the "implicit declaration" and "conflicting types" warnings, it's because in older standards of C it was allowed to not declare functions and the compiler would create an implicit declaration by guessing the declaration based on the first call of the function.
The important part about the guessing is that only the arguments were guessed, the return type would always be int.
I don't know the exact wording in the specifications about this since it was removed in the C99 specification, but most compilers still allow this with only emitting a warning instead of an error. This is where the first warning comes from.
However, the return type of int is still being used. And since your f1_1 function is declared to return void later in the file1.c source file, there's a mismatch between the guessed declaration (int f1_1(int)) and the actual declaration (void f1_1(int)) which leads to the second warning.
I have following three files. In the header file, I declare a global variable and tried to access it other files using extern. But I got the linker errors.
Header1.h
#ifndef HEADER1_H
#define HEADER1_H
#include<stdio.h>
int g = 10;
void test();
#endif
test.c
#include "header1.h"
extern int g;
void test()
{
printf("from print function g=%d\n", g);
}
main.c
#include "header1.h"
extern int g;
int main()
{
printf("Hello World g=%d\n", g);
test();
getchar();
return 0;
}
Linker error:
LNK2005 "int g" (?g##3HA) already defined in main.obj
LNK1169 one or more multiply defined symbols found
My understanding about extern is that a variable can be defined only once but can be declared multiple times. I think I follow it this way - I defined the global variable g in the header file and tried to access it in the .c files.
Could you please correct my understanding? What actually causes the linker error here? I did not define g multiple times.
You get a multiple definition error because you put the definition in the header file. Because both source files include the header file, that results in g being defined in both places, hence the error.
You want to put the declaration in the header file and the definition in one source file:
In header1.h:
extern int g;
In test.c:
int g = 10;
And nothing in main.c.
I have two files.
The first file contains the function prototype and the main function calls myfunc with only one argument:
int myfunc (int x);
int main ()
{
int x =5;
myfunc(x);
}
and the second file contains the function definition but with 2 arguments:
int myfunc (int x, int y)
{
return x+y;
}
When I tried to compile this two files using GCC I got no errors or warnings.
How to force GCC to warn about something like this??
Put your prototypes in a header file, and #include the header file in all source files which use the functions.
GCC compiles each file independently, so it cannot know that the definition of the function does not correspond to the declaration unless the declaration is also included in the file with the definition.
It should look like this:
myfunc.h
#ifndef MYFUNC_H
#define MYFUNC_H
int myfunc (int x);
#endif
myfunc.c
#include "myfunc.h"
int myfunc (int x, int y)
{
return x+y;
}
main.c
#include "myfunc.h"
int main ()
{
int x =5;
myfunc(x);
}
Because the two source files are two different translation units that are compiled completely separately, it's impossible for the compiler to know about this. And as C symbols doesn't really have information about arguments, the linker can't warn about this either.
The only solution is to put function prototypes in header files that are included in all relevant source files.
So I have several C files I imported into my XCode project. The primary C file contains the following function:
void myFunction (char* arg1, int arg2, int arg3, int arg4) {
// My code here
}
I then created the following header file for this file, including it in both the original C file and the .mm file I'm calling the function from
#ifndef _HEADER_H
#define _HEADER_H
// ...
/* Function prototype */
void myFunction(char*, int, int, int);
#endif
Finally, in my .mm file, I try calling it:
myFunction(myString, 100, 50, 32);
And I get the following linker error:
Undefined symbols for architecture x86_64:
"myFunction(char*, int, int, int)", referenced from:
-[TestFile awakeFromNib] in TestFile.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Yet, if I modify my C file to look like the following:
void testFunction() {
myFunction("test", 1, 2, 3);
}
void myFunction (char* arg1, int arg2, int arg3, int arg4) {
// My code here
}
And comment out the line in the .mm file, it works fine. It only occurs when I try to access myFunction() from the .mm file. Any ideas what might be causing this? I had read about issues with mixing C++ and Obj-C but never with just straight up C. Any help is greatly appreciated. Thanks!
When you include the c function, in your .mm file you need to use extern "C", something like this
extern "C" {
# include "c-header.h"
}
or, you can just add the extern "C" to the function declaration.
The reason to do this is name mangling which is used in c++ to allow function overloading, the real function name gets modified by the compiler depending on it's arguments.
The reason why omitting the arguments work, is probably because the mangled name is the same to the original name when the function does not specify arguments.
Look at any foundation's function prototype.
They all have prefix CF_EXTERN.
You should also write this prefix for function prototypes that you are planning for calling in objective-c,c++ and objective-c++ code.
Of course with that prefix you will lose c++'s function overloading feature.