I'm currently working on some code written in C, I've never done C programming before; only Java and a little bit of Python. I'm currently in the process of learning C, so whatever I write may not be the best way to do "that" thing. But as I keep learning new things, I'll blog them when I find time. So if you're interested in learning C, follow my posts; especially if you're a Java programmer who doesn't know C but you're interested just for the heck of it. You may find these posts useful.</skippable>
I'd to call a few C++ class's methods from a C program recently, and I didn't know how to do it. I found a way that suits my situation and here it is.
The fact as I found out is that you cannot create an instance of a C++ object in your C program and obviously that means you can't call its methods. So, we need a workaround. In general, we need to be able to do these things from our C code:
- Create an instance of a C++ class
- Call its methods, pass arguments, etc.
- Destroy the created instance.
(Instance == Object). Just thought I should let you know!
I'll demonstrate the process with an example. So up first, let's create a C++ class which we'll call from a C program.
// cppclass.cpp
class CppClass
{
public:
char *returnHello()
{
char *ret_val = "Hello";
return ret_val;
}
};
But I've already told you that we can't create an instance of this class directly, so we've to provide wrapper functions that our C program can call. The disadvantage with this workaround is, for every public function we want to use we need a wrapper function. Anyway, let's write them.
(Add the following lines to cppclass.cpp file)
extern "C" void *create_cppclass() { return new CppClass(); } extern "C" char *call_return_hello(void *obj) { return reinterpret_cast<CppClass*>(obj)->returnHello(); } extern "C" void *free_cppclass(void *obj) { delete reinterpret_cast<CppClass*>(obj); }
A few things should be noticed here.
- All these wrapper functions are preceded with extern "C" (uppercase C)
- In create_cppclass() wrapper function, the newly created object of CppClass is returned as a void pointer (void *). Void pointers can be used to point to any type. So when we return the instance as a pointer to void in this function, it can stored it in our C program. That's the whole point here.
- In call_return_hello() and free_cppclass() wrapper functions, we use reinterpret_cast to convert the void pointer back to CppClass pointer type. The -> operator is used for dereferencing the pointers instead of the . (dot) operator.
Now, let's call these functions from our C program. We should declare these functions first in our C program before we can use them.
// cfile.c
#include <stdio.h>
extern "C" void *create_cppclass();
extern "C" char *call_return_hello(void *obj);
extern "C" void *free_cppclass(void *obj);
main()
{
void *obj = create_cppclass();
char *hello = call_return_hello(obj);
free_cppclass(obj);
printf("%s\n", hello);
}
Now, I'll use g++ to compile:
g++ -o go cfile.c cppclass.cpp
./go
-o indicates the executable output file name which is "go" here. Write the code and try out for yourself. It should print "Hello" (Duh!)
That's it.