I try to compile my very first program in C++ in which I try to connect to ZooKeeper and do some other stuff. In my code I have these lines:
//test.cpp
#include "zookeeper.h"
... all other header files from zookeeper/include
void main_watcher (zhandle_t *zkh,
int type,
int state,
const char *path,
void* context)
{
if(type == ZOO_SESSION_EVENT){
if(state == ZOO_CONNECTED_STATE){
...
}
...
}
}
int main(){
return 0;
}
But when I compile this test.cpp file (indeed, I provide link to the zookeeper/.../build/usr/lib and path to all included files), I get a list of these error messages:
undefined reference to ZOO_SESSION_EVENT
undefined reference to ZOO_CONNECTED_STATE
...
What am I doing wrong?
You're forgetting to link agains zookeeper, most probably. Typically, you'd have to do something like
g++ -lzookeper -o yourprogram yourprogram.c
maybe it's
-lzookeeper-mt
maybe not. Usually, it's job of a build system to figure these things out for you.
Related
NOTE: This is not about C/C++ linkage or the extern keyword. Please read carefully before associating my question with seemingly similar questions, thank you!
I think this is a somewhat unusual problem as I didn't find anything on this while browsing the web.
I'm programming an embedded system. The main module is written in C while a submodule is written in C++. To illustrate this:
submodule.hpp
/ \
/ \
main.c submodule.cpp
Now I want to hold on to the data that is used by the C++-submodule and contain it in a static variable in my main script so I can call submodule functions from main and provide context data with every call. But that data must also contain a class as it is used by the submodule functions, but of course C doesn't know how to deal with classes. So I have to covertly put a class into my C-struct without main.c-script noticing (giving me an error). How could I achieve this?
I figured something like this could work:
struct data_for_cpp_submodule {
int a;
int b;
void *class;
}
And then casting the void pointer "class" back to the appropriate class so I can work with it in the C++ script. Could this work or am I going about it completely the wrong way?
Please, note that OP emphasized:
The main module is written in C while a submodule is written in C++.
IMHO, it's completely fine to add a C binding for the C++ submodule, so that it can be used in C code.
The example of OP (enhanced a bit to make it an MCVE):
C++ code for submodule:
header submodule.hpp:
#ifndef SUB_MODULE_HPP
#define SUB_MODULE_HPP
class Test {
private:
int a = 0;
int b = 0;
public:
Test() = default; // default constructor
Test(int a, int b): a(a), b(b) { } // value constructor
Test(Test&) = delete; // say: copy constructor disabled
Test& operator=(Test&) = delete; // say: copy assignment disabled
public:
int exec() const;
};
#endif // SUB_MODULE_HPP
source submodule.cpp:
#include "submodule.hpp"
int Test::exec() const { return a + b + 42; }
C Binding for submodule:
header: submodule.h
#ifndef SUB_MODULE_H
#define SUB_MODULE_H
#ifdef __cplusplus
extern "C" {
#endif
struct TestC_;
typedef struct TestC_ TestC; // opaque structure
extern TestC* testNew();
extern TestC* testNewValues(int a, int b);
extern void testDelete(TestC *pTest);
extern int testExec(TestC *pTest);
#ifdef __cplusplus
}
#endif
#endif // SUB_MODULE_H
source submoduleC.cpp:
#include "submodule.h"
#include "submodule.hpp"
TestC* testNew() { return (TestC*)new Test(); }
TestC* testNewValues(int a, int b) { return (TestC*)new Test(a, b); }
void testDelete(TestC *pTest) { delete (Test*)pTest; }
int testExec(TestC *pTest) { return ((Test*)pTest)->exec(); }
Last but not least: A sample C program using submodule:
#include <stdio.h>
#include "submodule.h"
int main(void)
{
TestC *pTest = testNew();
printf("pTest->exec(): %d\n", testExec(pTest));
testDelete(pTest);
pTest = testNewValues(123, -123);
printf("pTest->exec(): %d\n", testExec(pTest));
testDelete(pTest);
}
How it has to be compiled and linked with g++/gcc:
$ ## compile C++ code
$ g++ -std=c++17 -O2 -Wall -pedantic -c submodule.cpp submoduleC.cpp
$ ## compile C code
$ gcc -std=c11 -O2 -Wall -pedantic -lstdc++ main.c submodule.o submoduleC.o
$ ## test
$ ./a.out
Output:
testExec(pTest): 42
testExec(pTest): 42
Demo on coliru
The most notable part might be the opaque structure:
struct TestC_;
typedef struct TestC_ TestC; // opaque structure
(This is what I learnt from other C bindings before I started to write my own.)
It might be surprising that the opaque structure is actually an incomplete structure but that's intentional.
The opaque structure is intended to be used as pointer only in C. It's not intended to allow dereferencing of any contents (and, for an incomplete structure, this is merely denied by the compiler). It's only purpose is to "tunnel" a pointer to a C++ Test instance through the C code.
In the C binding of Test (submoduleC.cpp), TestC* is simply converted to Test* (and vice versa) where necessary.
Hint:
I had to link -lstdc++ (the standard C++ library). Otherwise, I got complaints about undefined references for the operators new and delete:
submoduleC.o: In function `testNew':
submoduleC.cpp:(.text+0xa): undefined reference to `operator new(unsigned long)'
submoduleC.o: In function `testNewValues':
submoduleC.cpp:(.text+0x30): undefined reference to `operator new(unsigned long)'
submoduleC.o: In function `testDelete':
submoduleC.cpp:(.text+0x4b): undefined reference to `operator delete(void*, unsigned long)'
collect2: error: ld returned 1 exit status
Other thoughts (but probably not that relevant):
I remember a prominent framework which
is written in C
and provides a C++ API (aka. C++ binding).
I'm talking about GTK+ and gtkmm (its C++ binding).
Thereby, it should be mentioned that GTK+ is actually an OOP library – providing object-oriented classes implemented in C. (I'm uncertain whether this fact makes things easier or harder concerning the C++ binding.)
Both are Open Source projects. Hence, everybody can have a look at it how did they do. I once had a look and was impressed…
This aside, I always would recommend the opposite: writing a library in C++ and adding a C binding as this appears much easier to me.
We always did this in Windows for multiple reasons:
to achieve that DLLs compiled with different versions of Visual Studio can be linked together. (Until soon, this was nearly impossible with C++ but now, I believe, I read about an ABI introduced by Microsoft which may it make possible.)
to provide a base for bindings in other languages like e.g. C#.
Edit: ***Sorry I realize there must have been some misunderstanding when posting this question, I want to specify that I DO realize this question was asked a few times, none of the answers work for me however***
I've been trying to link a simple static library test to one of my c++ projects, but I can't seem to get it quite right. I know that this is a very widespread topic and that a lot of people have already asked a similar question, but even after reading some of the answers, I still cannot, for the love of god, figure out what I am doing wrong.
My code is very simple, first I have a .cpp source file titled "Math.cpp" that looks like this:
#include "Math.h"
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a < b ? a : b;
}
int floor(double a) {
return (int) a;
}
int ceil(double a) {
return (int) a + 1;
}
..And to go with that I made a header file called "Math.h" that looks like this:
#pragma once
int max(int, int);
int min(int, int);
int floor(double);
int ceil(double);
I then compile "Math.cpp" with the following command on cmd:
g++ -c Math.cpp -o Math.o
...and then compile it into a static library like so:
ar rcs libMath.a Math.o
After all of this I make a new c++ soure file titled "Main.cpp" that looks like this:
#include <iostream>
#include "Math.h"
int main() {
std::cout << max(9, 8) << std::endl;
return 0;
}
("Math.h" is in the same directory as "Main.cpp")
So finally in order to link "Main.cpp" with my static library ("libMath.a"), I use the following command in cmd:
g++ -o Main.exe Main.cpp -L. -lMath
however, at this point, it throws the following error:
C:\Users\zalmar\AppData\Local\Temp\ccmOnvyg.o:Main.cpp:(.text+0x18): undefined reference to `max(int, int)'
collect2.exe: error: ld returned 1 exit status
... I cannot figure out why it can't find the reference to the specific function. Some people appeared to have the same problem (here for example). Their solution was to declare the Main.cpp source file before declaring the library path. However, that was not the case for me, even though I made sure I was linking the library after the Main.cpp it still came up with the same error. I would greatly appreciate it if someone could point out anything I might be doing wrong because clearly I must be doing something wrong. Otherwise it might be a problem with my MinGW compiler, maybe?
I also want to re-mention that this is just a test library and I am fully aware that it might be a bit overkill to compile an entire static library from such a simple program. I am simply trying to figure out how to link libraries to my c++ projects...
I have problem and no idea how to resolve it. I believe this is stupid trivial:
I have 3 files:
Util.hpp
class Util
{
public:
class BitParser
{
public:
static bool getBitAt(int buf, int idx);
};
};
Util.cpp
#include "Util.hpp"
bool Util::BitParser::getBitAt(int buf, int idx)
{
return true;
}
application.cpp
#include "Util.hpp"
int main(int argc, char* argv[])
{
Util::BitParser::getBitAt(1,1);
}
Of couse, files listed above are in the same directory. And now when I try to link and compile I recieve linker error:
$ g++ -o app application.cpp
application.cpp:(.text+0x19): undefined reference to `Util::BitParser::getBitAt(int, int)'
collect2: ld returned 1 exit status
What is screwed up?
You told g++ to compile your 'main' program, but didn't tell it about the Util module. Add Util.cpp to the command line and all should work well.
The compiler has brewn an "application.o" file that refers to the Util::bitparser functions.
The linker should 'link' these referrals to the "util.o" file, containing the actual code for these functions. But it has no .o file containing a function satisfying the link. That's what it calls "undefined reference": "application.o" refers to a function the linker doesn't find.
You need to compile (and link) all the .cpp files. So in your case, the command would be
$ g++ -o app application.cpp Util.cpp
Better still, write a Makefile to do this for you.
You have to include both application.cpp and Util.cpp in the build.
I want to call a function from C++ library on linux. I have a shared object of that library.
I want to call method getAge() that return an int from ydmg library.
Following is the code that I have written:
testydmg.cpp
#include "ydmg/bd.h"
#include "yut/hash.h"
#include "dlfcn.h"
extern "C" int getAge();
class testydmg{
public:
testydmg::testydmg(const yutHash& user){
}
testydmg::testydmg(){
}
testydmg::~testydmg(){
}
int testydmg::getFunction(){
void *handle;
int (*voidfnc)();
handle = dlopen("ydmg.so",RTLD_LAZY);
if(handle == NULL){
printf("error in opening ydmg lib");
} else {
voidfnc = (int (*)())dlsym(handle, "getAge");
(*voidfnc)();
printf("class loaded");
}
ydmgBd obj;
obj.getAge();
printf("Inside getFunction()...");
dlclose(handle);
}
};
I compile and link the code as below:
gcc -fPIC -shared -l stdc++ -I/home/y/libexec64/jdk1.6.0/include -I/home/y/libexec64/jdk1.6.0/include/linux -I/home/y/include testydmg.cpp -o libTestYdmg.so libydmg.so
Then I check for the method in the new shared object i.e. libTestYdmg.so
nm -C libTestYdmg.so | egrep getAge
I get nothing by running the above command.
Does it mean that it did not get the method getAge() from the library.
Could you please correct where I am going wrong ?
You want to use ydmgDB::getAge() but you are asking to the library for getAge(). This is not correct, just simply create a ydmgDBobject and invoke it's method getAge() without loading the library that is linked with your compile command line.
You don't need to dlopen the library.
Besides, getAge is not really included in libTestYdmg.so. You must look for it in libydmg.so using:
nm -C libydmg.so | grep getAge
If you're interested in actually using dlopen in C++ code, take a look at the
C++ dlopen mini HOWTO, which includes example code and some possibly important
warnings.
I am new to the forum i wanted to call a member function of an included header file..Here is code i have written
#include<stdio.h>
#include "Abc.h"
CAbc *a;//CAbc is a class present in Abc.h
int main(int argc,char **argv)
{
int i=10;
float j=15.5;
bool x;
x=a->method(i,j);//method is a member function of CAbc
if(x)
{
printf("Working Correctly");
}
else
{
printf("Not Working");
}
}
If i compile this using
g++ -I/path/to/include code.cpp
I get the Error
/tmp/cc5JgLfF.o: In function `main':
code.cpp:(.text+0x3d): undefined reference to `CAbc::method(int,float)'
collect2: ld returned 1 exit status
I also tried giving
x=a::method(i,j);
for which i get a is not a class or namespace
Please can anyone tell me am i doing it correctly or not?
It looks as though you are forgetting to include the implementation source/object.
Try this:
g++ -I/path/to/include Abc.cpp code.cpp
as long as your implementation class for Abc.h corresponds to Abc.cpp.
Regards,
Dennis M.
Does your make file or whatever link CABC.obj to the whole exe? If so, then you have forgotten to write the implementation (body, definition) of method...
As others have said, make sure there's an implementation of CAbc.method being linked. Additionally, you need to allocate and deallocate the memory for pointer 'a'; at the moment it's uninitialized.
a = new CAbc();
...
del a