Recently one of my friend asked this question. I had done this in past but I had to struggle to do this again. So I am documenting this in case i need this again in future.
Let's first create a C++ shared library containing the functions we need.
Since, I am not good with names so I'll call it the "Person" class.
Person.h
Person.cpp
After creating the source files we need to compile them into shared object.
At this point we have our C++ shared library.
A simple client in C++ for this library looks like this.
Client.cpp
We can compile and run this small program as such. We need to export LD_LIBRARY_PATH before running the binary, so that the loader can find the shared object.
Till here we know that everything works.
Now, lets call these methods from C code. But, as we know that C++ does name mangling we cannot directly call these methods from the C code. We first have to write some kind of wrapper over the existing library using C naming convention so that the names are not mangled.
Here is what the wrapper class looks like
Wrapper.cpp
This will be our wrapper shared library over the libPerson.so library. lets compile and create the library.
Now, its time to write our Client in C; it looks like this
Client.c
And, we're done !!
Any comments/suggestions are welcomed !!
Let's first create a C++ shared library containing the functions we need.
Since, I am not good with names so I'll call it the "Person" class.
Person.h
#ifndef __PERSON_H__ #define __PERSON_H__ void globalMethod(); class Person { public: void instanceMethod(); static void classMethod(); }; #endif
Person.cpp
#include "Person.h" #include <iostream> using namespace std; void globalMethod() { cout<<"Global method"<<endl; } void Person::instanceMethod() { cout<<"Instance method"<<endl; } void Person::classMethod() { cout<<"Class method"<<endl; }
After creating the source files we need to compile them into shared object.
$ g++ -fPIC -c Person.cpp
$ g++ -shared -o libPerson.so Person.o
$
At this point we have our C++ shared library.
A simple client in C++ for this library looks like this.
Client.cpp
#include "Person.h" int main() { Person p; p.instanceMethod(); Person::classMethod(); globalMethod(); }
We can compile and run this small program as such. We need to export LD_LIBRARY_PATH before running the binary, so that the loader can find the shared object.
$ g++ Client.cpp -o Client -L. -lPerson
$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
$ ./Client
Instance method
Class method
Global method
$
Till here we know that everything works.
Now, lets call these methods from C code. But, as we know that C++ does name mangling we cannot directly call these methods from the C code. We first have to write some kind of wrapper over the existing library using C naming convention so that the names are not mangled.
Here is what the wrapper class looks like
Wrapper.cpp
#include "Person.h" extern "C" void GlobalMethod() { globalMethod(); } extern "C" void InstanceMethod(Person *p) { p->instanceMethod(); } extern "C" void ClassMethod() { Person::classMethod(); }Note the InstanceMethod() takes a pointer to Person object. Why ??? Remember the *this* pointer in C++; since this method will be called from C code, we need to manually pass this variable.
This will be our wrapper shared library over the libPerson.so library. lets compile and create the library.
$ g++ -fPIC -c Wrapper.cpp
$ g++ -shared -o libWrapper.so Wrapper.o
$
Now, its time to write our Client in C; it looks like this
Client.c
struct Person { }; int main(){ GlobalMethod(); struct Person p; InstanceMethod(p); ClassMethod(); }Pay attention that we have to create a Struct for the Person class. We need to link this binary against the wrapper library (libWrapper.so) and the actual library(libPerson.so), since the Wrapper depends upon it.
$ gcc Client.c -o C_Client -L. -lWrapper -lPerson
$ ./C_Client
Global method
Instance method
Class method
$
And, we're done !!
Any comments/suggestions are welcomed !!
No comments:
Post a Comment