Calling a C++ Shared Lib within a C program...how to manage? - c++

i'd like to write a wrapper for a C++ framework. this framework is kinda buggy and not really nice and in C++. so i'd like to be able to call their methods from outside (via good old C file) of their framework by using just one shared lib. this sounds like the need for a wrapper that encapsulates the wanted framework methods for usage with C instead of C++.
So far so good.... here is what i already did:
interface aldebaran.h
(this is in my include folder, the ultrasound methods should be called from outside of the framework):
#ifndef _ALDEBARAN_H
#define _ALDEBARAN_H
#ifdef __cplusplus
extern "C" {
#endif
void subscribe_ultrasound();
void unsubscribe_ultrasound();
float read_ultrasound();
#ifdef __cplusplus
}
#endif
#endif
now the wrapper:
cpp file aldebaran.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aldebaran.h"
#include "alproxy.h"
#include "../../include/aldebaran.h"
/*
* Ultrasound defines
*/
#define ULTRASOUND_RESERVATION_MAGIC "magic_foobar"
#define ULTRASOUND_POLL_TIME 250
#define ULTRASOUND_READ_ATTEMPTS 50
#define ULTRASOUND_SLEEP_TIME 20
using namespace std;
using namespace AL;
/*
* Framework proxies
*/
ALPtr<ALProxy> al_tts;
ALPtr<ALProxy> al_led;
ALPtr<ALProxy> al_motion;
ALPtr<ALProxy> al_mem;
ALPtr<ALProxy> al_us;
ALPtr<ALProxy> al_cam;
ALPtr<ALProxy> al_dcm;
/*
* Constructor
*/
Aldebaran::Aldebaran(ALPtr<ALBroker> pBroker, std::string pName): ALModule(pBroker, pName)
{
try {
al_tts = this->getParentBroker()->getProxy("ALTextToSpeech");
al_led = this->getParentBroker()->getProxy("ALLeds");
al_motion = this->getParentBroker()->getProxy("ALMotion");
al_mem = this->getParentBroker()->getProxy("ALMemory");
al_us = this->getParentBroker()->getProxy("ALUltraSound");
al_cam = this->getParentBroker()->getProxy("NaoCam");
al_dcm = this->getParentBroker()->getProxy("DCM");
}catch(ALError& err){
std::cout << "XXX: ERROR: " << err.toString() << std::endl;
return 1;
}
printf("XXX: module aldebaran initiated\n");
fflush(0);
}
/*
* Destructor
*/
Aldebaran::~Aldebaran()
{
printf("XXX: module aldebaran destructed\n");
fflush(0);
}
/*
* Subscribe to ultrasound module
*/
void subscribe_ultrasound()
{
ALValue param;
param.arrayPush(ULTRASOUND_POLL_TIME);
al_us->callVoid("subscribe", string(ULTRASOUND_RESERVATION_MAGIC), param);
printf("XXX: ultrasound subscribed: %s\n", ULTRASOUND_RESERVATION_MAGIC);
fflush(0);
}
/*
* Unsubscribe to ultrasound module
*/
void unsubscribe_ultrasound()
{
al_us->callVoid("unsubscribe", string(ULTRASOUND_RESERVATION_MAGIC));
printf("XXX: ultrasound unsubscribed: %s\n", ULTRASOUND_RESERVATION_MAGIC);
fflush(0);
}
/*
* Read from ultrasound module
*/
float read_ultrasound()
{
int i;
float val1, val2;
float val_sum;
ALValue distance;
val_sum = .0f;
for(i = 0; i < ULTRASOUND_READ_ATTEMPTS; ++i){
SleepMs(ULTRASOUND_SLEEP_TIME);
distance = al_mem->call<ALValue>("getData", string("extractors/alultrasound/distances"));
sscanf(distance.toString(AL::VerbosityMini).c_str(),"[%f, %f, \"object\"]", &val1, &val2);
val_sum += val1;
}
return val_sum / (1.f * ULTRASOUND_READ_ATTEMPTS);
}
definition file for aldebaran.cpp:
#ifndef ALDEBARAN_API_H
#define ALDEBARAN_API_H
#include <string>
#include "al_starter.h"
#include "alptr.h"
using namespace AL;
class Aldebaran : public AL::ALModule
{
public:
Aldebaran(ALPtr<ALBroker> pBroker, std::string pName);
virtual ~Aldebaran();
std::string version(){ return ALTOOLS_VERSION( ALDEBARAN ); };
bool innerTest(){ return true; };
};
#endif
So this should be a simple example for my wrapper and it compiles fine to libaldebaran.so.
now my test program in C:
... now i'd like to call the interface aldebaran.h methods from a simple c file like this:
#include <stdio.h>
/*
* Begin your includes here...
*/
#include "../include/aldebaran.h"
/*
* End your includes here...
*/
#define TEST_OKAY 1
#define TEST_FAILED 0
#define TEST_NAME "test_libaldebaran"
unsigned int count_all = 0;
unsigned int count_ok = 0;
const char *__test_print(int x)
{
count_all++;
if(x == 1){
count_ok++;
return "ok";
}
return "failed";
}
/*
* Begin tests here...
*/
int test_subscribe_ultrasound()
{
subscribe_ultrasound();
return TEST_OKAY;
}
int test_unsubscribe_ultrasound()
{
unsubscribe_ultrasound();
return TEST_OKAY;
}
int test_read_ultrasound()
{
float i;
i = read_ultrasound();
return (i > .0f ? TEST_OKAY : TEST_FAILED);
}
/*
* Execute tests here...
*/
int main(int argc, char **argv)
{
printf("running test: %s\n\n", TEST_NAME);
printf("test_subscribe_ultrasound: \t %s\n", __test_print(test_subscribe_ultrasound()));
printf("test_read_ultrasound: \t %s\n", __test_print(test_read_ultrasound()));
printf("test_unsubscribe_ultrasound: \t %s\n", __test_print(test_unsubscribe_ultrasound()));
printf("test finished: %s has %u / %u tests passed\n\n", TEST_NAME, count_ok, count_all);
return (count_all - count_ok);
}
how can i manage to call these methods? i mean within my C file i have no possibility to create such an object-instance (that generated all the needed ALProxies), have i?
help would be really appreciated... thx
thank you very much so far!!
as xtofl said.. i'd like to keep my interface as simple as possible (without another c++ object preferably):
#ifndef _ALDEBARAN_H
#define _ALDEBARAN_H
#ifdef __cplusplus
extern "C" {
#endif
void subscribe_ultrasound();
void unsubscribe_ultrasound();
float read_ultrasound();
#ifdef __cplusplus
}
#endif
#endif
the problem hereby is that functions like subscribe_ultrasound() cannot be called without the instanciation of all the proxies... this is our precondition:
...
al_tts = this->getParentBroker()->getProxy("ALTextToSpeech");
al_led = this->getParentBroker()->getProxy("ALLeds");
al_motion = this->getParentBroker()->getProxy("ALMotion");
al_mem = this->getParentBroker()->getProxy("ALMemory");
al_us = this->getParentBroker()->getProxy("ALUltraSound");
al_cam = this->getParentBroker()->getProxy("NaoCam");
al_dcm = this->getParentBroker()->getProxy("DCM");
...
if i don't have the code above called, all other will fail.
within their framework it is possible to "autoload" my libaldebaran.so via a python script like this call:
myModule = ALProxy("Aldebaran", global_params.strRemoteIP, global_params.nRemotePort );
The framework log then says:
May 10 15:02:44 Hunter user.notice root: XXX: module aldebaran initiated
May 10 15:02:46 Hunter user.notice root: INFO: Registering module : 'Aldebaran'
May 10 15:02:46 Hunter user.notice root: ______ End of loading libraries ______
which is totally okay... it called the constructor of my module (so all other needed proxies got instanciated too).
but of course this instance does not belong to my C program...
maybe there is a possibility to share this to all other processes?

You might want to take a slightly different approach. Consider something like this for your C interface:
#ifdef __cplusplus
extern "C" {
#endif
struct UltrasoundHandle;
UltrasoundHandle* ultrasound_Create();
void ultrasound_Destroy(UltrasoundHandle *self):
void ultrasound_Subscribe(UltrasoundHandle *self);
void ultrasound_Unsubscribe(UltrasoundHandle *self);
float ultrasound_Read(UltrasoundHandle *self);
#ifdef __cplusplus
}
#endif
The UltrasoundHandle structure is purposefully opaque so that you can define it in the implementation to be whatever you want it to be. The other modification that I made was to add explicit creation and destruction methods akin to the constructor and destructor. The implementation would look something like:
extern "C" {
struct UltrasoundHandle {
UltrasoundHandle() {
// do per instance initializations here
}
~UltrasoundHandle() {
// do per instance cleanup here
}
void subscribe() {
}
void unsubscribe() {
}
float read() {
}
};
static int HandleCounter = 0;
UltrasoundHandle* ultrasound_Create() {
try {
if (HandleCounter++ == 1) {
// perform global initializations here
}
return new UltrasoundHandle;
} catch (...) {
// log error
}
return NULL;
}
void ultrasound_Destroy(UltrasoundHandle *self) {
try {
delete self;
if (--HandleCounter == 0) {
// perform global teardown here
}
} catch (...) {
// log error
}
}
The key is to wrapping C++ interfaces for C is to expose the OO concepts through free functions where the caller explicitly passes the object pointer (this) to the function and to explicitly expose the constructor and destructor in the same manner. The wrapper code can be almost mechanically generated from there. The other key points are that you never let exceptions propagate outward and steer clear of global object instances. I'm not sure if the latter will cause you grief, but I would be concerned about construction/destruction ordering problems.

You said yourself to create a C wrapper API around an OO framework.
This means you don't need any objects passing the wrapper API (as it appears from the decribed header). It seems all objects needed are created/destructed behind the wrapper API, out of view of your test program.
The first seems the case. You don't need objects to test your wrapper API. In the end, all objects are bytes (in memory) that are accessed through a fixed set of functions. It doesn't matter much whether the functions are written as member-functions (C++) or as plain C functions, as long as they obey the intended semantics of your objects.

I'm not clear whether you're aware of this, but if you have C++ code to dynamically load into your program, then you should link your program with the C++ compiler and make your main function a C++ function too - even if it is as trivial as:
int main(int argc, char **argv)
{
return(real_main_in_c(argc, argv));
}
The real_main_in_c() function is what you previously called main(); it has simply been renamed. This ensures that the C++ mechanisms for handling initialization of global and static variables, etc, are loaded and operational. The C++ startup code does more work than the C startup code. Dynamically loading C
This is only one (small) facet of the answer - but it is an important practical one.

Keep things as simple as possible - but not simpler. I think you're trying to make it too simple here, wrap it all up but use the c++ compiler.
so, if you create your wrapper using the c++ compiler, you can instantiate the objects inside your subscribe function, release them all in the unsubscribe, all using static (or global) objects. The 3 functions you want to expose simple get wrapped with "extern C" and you have a C-style interface exposed to any caller, whilst still encapsulating C++ objects.
If you need another function to instantiate all the proxies, add one; alternatively if they don't already exist, create them so they'll always be created in the first call to subscribe.
Now, if you need the proxy objects on a per-instance basis (ie you have 2 callers who both want to subscribe, and need a unique proxy per caller), then you'll have to store the objects in a collection (I suggest a map), every call you make must then pass in a 'handle' or 'sessionid' that you use to extract the per-call objects from the map.

Related

Can we create a C++ string object from char pointer where the operations on the string object reflects to the source char pointer?

I've been trying to use C++ string class rich methods (find_first_of, replace) for some string processing for a task.
And i created a wrapper file around the above mentioned code, where it can be included in 'C' source files and get the functionality.
strUtils.h
#ifdef __cplusplus
extern "C" {
#endif
void doTheStringWork(char *inStr, unsigned beginLoc);
#ifdef __cplusplus
}
#endif
strUtils.cpp
#include "strUtils.h"
/*some standard includes here*/
void doTheStringWork(char *inStr, unsigned beginLoc) {
std::string inStr_s(inStr);
/* Doing some processing with the string object inStr_s*/
/* .......*/
/* Done */
return;
}
And now i'm stuck with one problem which cannot be solved without making copies as far as i know. So, i seek your help in this.
The problem is i need to get the changes done by doTheStringWork function back at the caller's place. You may say take .c_str() value as return from func or get a copy somehow. That approaches works well but for my tasks it becomes very slow approach since the string can be too long and i might require it to process recursively.
In plain words: can we create a string object around a char pointer where i can use all string functions and the char pointer reflects all these changes. If such thing cannot be achieved using standard library could someone provide an approach how can i achieve my goal here.
Best solution is to dump C, use C++ and get away from whole mess. But since you probably can't do that, next best solution is to create your own C visible struct and some C visible functions (essentially PIMPL), define those in C++ source (so you get benefits of std::string) and use them from C. Something like this.
In strUtils.h header:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cpp_string cpp_string;
cpp_string *cpp_string_create(const char *txt, int size);
void cpp_string_free(cpp_string *);
cpp_string *cpp_string_add(cpp_string *, cpp_string *);
... // all operations you need
#ifdef __cplusplus
}
#endif
In C++ source (strUtils.cpp):
#include <string>
struct cpp_string {
std::string str;
cpp_string(std::string str): str(std::move(str)) { }
};
extern "C" cpp_string *cpp_string_create(const char *txt, int size)
{
return new cpp_string{ std::string{ txt, (size_t)size } };
}
// fill operations here
// since this is C++ file, just use std::string without copying
Now, when you want to use it, you do something like this:
int main()
{
cpp_string *s = cpp_string_create("qwerty", 6);
// do something with s
// dont forget to free s
cpp_string_free(s);
return 0;
}
This sidesteps whole can-i-overwrite-someone-elses-memory (no, you can't, unless you want to have weird, wierd problems) by creating your own data.

How to wrapping in C a C++ function with vector<struct> output argument? [duplicate]

I'm looking to develop a set of C APIs that will wrap around our existing C++ APIs to access our core logic (written in object-oriented C++). This will essentially be a glue API that allows our C++ logic to be usable by other languages. What are some good tutorials, books, or best-practices that introduce the concepts involved in wrapping C around object-oriented C++?
This is not too hard to do by hand, but will depend on the size of your interface.
The cases where I've done it were to enable use of our C++ library from within pure C code, and thus SWIG was not much help. (Well maybe SWIG can be used to do this, but I'm no SWIG guru and it seemed non-trivial)
All we ended up doing was:
Every object is passed about in C an opaque handle.
Constructors and destructors are wrapped in pure functions
Member functions are pure functions.
Other builtins are mapped to C equivalents where possible.
So a class like this (C++ header)
class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}
Would map to a C interface like this (C header):
struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );
The implementation of the interface would look like this (C++ source)
#include "MyClass.h"
extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}
We derive our opaque handle from the original class to avoid needing any casting, and (This didn't seem to work with my current compiler). We have to make the handle a struct as C doesn't support classes.
So that gives us the basic C interface. If you want a more complete example showing one way that you can integrate exception handling, then you can try my code on github : https://gist.github.com/mikeando/5394166
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using g++.
I think Michael Anderson's answer is on the right track but my approach would be different. You have to worry about one extra thing: Exceptions. Exceptions are not part of the C ABI so you cannot let Exceptions ever be thrown past the C++ code. So your header is going to look like this:
#ifdef __cplusplus
extern "C"
{
#endif
void * myStruct_create( const char * s );
void myStruct_destroy( void * v );
int myStruct_doSomething( void * v, int i );
#ifdef __cplusplus
}
#endif
And your wrapper's .cpp file will look like this:
void * myStruct_create( const char * s ) {
MyStruct * ms = NULL;
try { /* The constructor for std::string may throw */
ms = new MyStruct(s);
} catch (...) {}
return static_cast<void*>( ms );
}
void myStruct_destroy( void * v ) {
MyStruct * ms = static_cast<MyStruct*>(v);
delete ms;
}
int myStruct_doSomething( void * v, int i ) {
MyStruct * ms = static_cast<MyStruct*>(v);
int ret_value = -1; /* Assuming that a negative value means error */
try {
ret_value = ms->doSomething(i);
} catch (...) {}
return ret_value;
}
Even better: If you know that all you need as a single instance of MyStruct, don't take the risk of dealing with void pointers being passed to your API. Do something like this instead:
static MyStruct * _ms = NULL;
int myStruct_create( const char * s ) {
int ret_value = -1; /* error */
try { /* The constructor for std::string may throw */
_ms = new MyStruct(s);
ret_value = 0; /* success */
} catch (...) {}
return ret_value;
}
void myStruct_destroy() {
if (_ms != NULL) {
delete _ms;
}
}
int myStruct_doSomething( int i ) {
int ret_value = -1; /* Assuming that a negative value means error */
if (_ms != NULL) {
try {
ret_value = _ms->doSomething(i);
} catch (...) {}
}
return ret_value;
}
This API is a lot safer.
But, as Michael mentioned, linking may get pretty tricky.
Hope this helps
It is not hard to expose C++ code to C, just use the Facade design pattern
I am assuming your C++ code is built into a library, all you need to do is make one C module in your C++ library as a Facade to your library along with a pure C header file. The C module will call the relevant C++ functions
Once you do that your C applications and library will have full access to the C api you exposed.
for example, here is a sample Facade module
#include <libInterface.h>
#include <objectedOrientedCppStuff.h>
int doObjectOrientedStuff(int *arg1, int arg2, char *arg3) {
Object obj = ObjectFactory->makeCppObj(arg3); // doing object oriented stuff here
obj->doStuff(arg2);
return obj->doMoreStuff(arg1);
}
you then expose this C function as your API and you can use it freely as a C lib with out worrying about
// file name "libIntrface.h"
extern int doObjectOrientedStuff(int *, int, char*);
Obviously this is a contrived example but this is the easiest way to expos a C++ library to C
I would think you may be able to get some ideas on direction and/or possibly utilize directly SWIG. I would think that going over a few of the examples would at least give you an idea of what kinds of things to consider when wrapping one API into another. The exercise could be beneficial.
SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Lua, Modula-3, OCAML, Octave and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG may be freely used, distributed, and modified for commercial and non-commercial use.
Just replace the concept of an object with a void * (often referred to as an opaque type in C oriented libraries) and reuse everything you know from C++.
I think using SWIG is the best answer... not only it avoid reinventing wheel but it is reliable and also promote a continuity in development rather than one shooting the problem.
High frequency problems need to be addressed by a long term solution.

Calling a Swift function from C++

I was wondering if it's possible to call a Swift function from C++? And if YES, how? I know that we can call a C++ function from Swift but I haven't found an exact answer about this.
While there’s no official way to call a Swift function directly from C, you can set up a function pointer that’s callable from C. Whether that helps you depends on your exact circumstances. For example, on Apple platforms it’s super useful for integrating with C APIs that use C callbacks (things like CFRunLoop observers).
Pasted in a below is an example sans anything Apple-ish.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "#apple.com"
// main.swift
private func printGreeting(modifier: UnsafePointer<CChar>) {
print("Hello \(String(cString: modifier))World!")
}
var callbacks = SomeCLibCallbacks(
printGreeting: { (modifier) in
printGreeting(modifier: modifier)
}
)
SomeCLibSetup(&callbacks)
SomeCLibTest()
// SomeCLib.h
#ifndef SomeCLib_h
#define SomeCLib_h
struct SomeCLibCallbacks {
void (* _Nonnull printGreeting)(const char * _Nonnull modifier);
};
typedef struct SomeCLibCallbacks SomeCLibCallbacks;
extern void SomeCLibSetup(const SomeCLibCallbacks * _Nonnull callbacks);
extern void SomeCLibTest(void);
#endif
// SomeCLib.c
#include "SomeCLib.h"
static SomeCLibCallbacks sCallbacks;
extern void SomeCLibSetup(const SomeCLibCallbacks * callbacks) {
sCallbacks = *callbacks;
}
extern void SomeCLibTest(void) {
sCallbacks.printGreeting("Cruel ");
}
Source: https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/2

Generator to change a C++ API into a C interface?

Is there some kind of tool i can give a c++ header to and have it change the API/lib/interface into a C interface as well as generate the C functions to cast and call the C++ code?
I think SWiG might do most of that.
I don't know of a tool that can do this automatically, it can get pretty tricky if you have classes as arguments to the public functions in your API.
But if your API is simple and mostly using native types, then you can do this by hand with not too much work. Here is a quick example of a C wrapper for a C++ class. Let's say this is the C++ class to wrap, let's call it test.h:
class Test {
public:
Test();
int do_something(char* arg);
bool is_valid(); // optional, but recommended (see below)
};
This is your C header test_c.h:
typedef void* TestHandle;
TestHandle newTest();
int deleteTest(TestHandle h);
int Test_do_something(TestHandle h, char* arg);
And your C implementation will be a C++ file with C functions, let's say test_c.cpp:
extern "C" TestHandle newTest()
{
return (void*)new Test();
}
extern "C" int deleteTest(TestHandle h)
{
Test* this = static_cast<Test*>(h);
if (!this->is_valid())
return -1; // here we define -1 as "invalid handle" error
delete this;
return 0; // here we define 0 as the "ok" error code
}
extern "C" int Test_do_something(TestHandle h, char* arg)
{
Test* this = static_cast<Test*>(h);
if (!this->is_valid())
return -1; // here we define -1 as "invalid handle" error
return this->do_something(arg);
}
The is_valid() method is there to guarantee that you were not given a bad handle. For example, you can store a magic number in all your instances, then is_valid() just ensures the magic number is there.

Developing C wrapper API for Object-Oriented C++ code

I'm looking to develop a set of C APIs that will wrap around our existing C++ APIs to access our core logic (written in object-oriented C++). This will essentially be a glue API that allows our C++ logic to be usable by other languages. What are some good tutorials, books, or best-practices that introduce the concepts involved in wrapping C around object-oriented C++?
This is not too hard to do by hand, but will depend on the size of your interface.
The cases where I've done it were to enable use of our C++ library from within pure C code, and thus SWIG was not much help. (Well maybe SWIG can be used to do this, but I'm no SWIG guru and it seemed non-trivial)
All we ended up doing was:
Every object is passed about in C an opaque handle.
Constructors and destructors are wrapped in pure functions
Member functions are pure functions.
Other builtins are mapped to C equivalents where possible.
So a class like this (C++ header)
class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}
Would map to a C interface like this (C header):
struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );
The implementation of the interface would look like this (C++ source)
#include "MyClass.h"
extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}
We derive our opaque handle from the original class to avoid needing any casting, and (This didn't seem to work with my current compiler). We have to make the handle a struct as C doesn't support classes.
So that gives us the basic C interface. If you want a more complete example showing one way that you can integrate exception handling, then you can try my code on github : https://gist.github.com/mikeando/5394166
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using g++.
I think Michael Anderson's answer is on the right track but my approach would be different. You have to worry about one extra thing: Exceptions. Exceptions are not part of the C ABI so you cannot let Exceptions ever be thrown past the C++ code. So your header is going to look like this:
#ifdef __cplusplus
extern "C"
{
#endif
void * myStruct_create( const char * s );
void myStruct_destroy( void * v );
int myStruct_doSomething( void * v, int i );
#ifdef __cplusplus
}
#endif
And your wrapper's .cpp file will look like this:
void * myStruct_create( const char * s ) {
MyStruct * ms = NULL;
try { /* The constructor for std::string may throw */
ms = new MyStruct(s);
} catch (...) {}
return static_cast<void*>( ms );
}
void myStruct_destroy( void * v ) {
MyStruct * ms = static_cast<MyStruct*>(v);
delete ms;
}
int myStruct_doSomething( void * v, int i ) {
MyStruct * ms = static_cast<MyStruct*>(v);
int ret_value = -1; /* Assuming that a negative value means error */
try {
ret_value = ms->doSomething(i);
} catch (...) {}
return ret_value;
}
Even better: If you know that all you need as a single instance of MyStruct, don't take the risk of dealing with void pointers being passed to your API. Do something like this instead:
static MyStruct * _ms = NULL;
int myStruct_create( const char * s ) {
int ret_value = -1; /* error */
try { /* The constructor for std::string may throw */
_ms = new MyStruct(s);
ret_value = 0; /* success */
} catch (...) {}
return ret_value;
}
void myStruct_destroy() {
if (_ms != NULL) {
delete _ms;
}
}
int myStruct_doSomething( int i ) {
int ret_value = -1; /* Assuming that a negative value means error */
if (_ms != NULL) {
try {
ret_value = _ms->doSomething(i);
} catch (...) {}
}
return ret_value;
}
This API is a lot safer.
But, as Michael mentioned, linking may get pretty tricky.
Hope this helps
It is not hard to expose C++ code to C, just use the Facade design pattern
I am assuming your C++ code is built into a library, all you need to do is make one C module in your C++ library as a Facade to your library along with a pure C header file. The C module will call the relevant C++ functions
Once you do that your C applications and library will have full access to the C api you exposed.
for example, here is a sample Facade module
#include <libInterface.h>
#include <objectedOrientedCppStuff.h>
int doObjectOrientedStuff(int *arg1, int arg2, char *arg3) {
Object obj = ObjectFactory->makeCppObj(arg3); // doing object oriented stuff here
obj->doStuff(arg2);
return obj->doMoreStuff(arg1);
}
you then expose this C function as your API and you can use it freely as a C lib with out worrying about
// file name "libIntrface.h"
extern int doObjectOrientedStuff(int *, int, char*);
Obviously this is a contrived example but this is the easiest way to expos a C++ library to C
I would think you may be able to get some ideas on direction and/or possibly utilize directly SWIG. I would think that going over a few of the examples would at least give you an idea of what kinds of things to consider when wrapping one API into another. The exercise could be beneficial.
SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Lua, Modula-3, OCAML, Octave and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG may be freely used, distributed, and modified for commercial and non-commercial use.
Just replace the concept of an object with a void * (often referred to as an opaque type in C oriented libraries) and reuse everything you know from C++.
I think using SWIG is the best answer... not only it avoid reinventing wheel but it is reliable and also promote a continuity in development rather than one shooting the problem.
High frequency problems need to be addressed by a long term solution.