Using a C++ library for a C application - c++

I have a command line (+HTTP interface) audio application in C, which currently is being compiled with gcc on Mac OSX, but which I would like to keep this application linux compatible.
However, I would like to use the freeverb3 library. This is in C++. I would prefer not to convert all my code to C++. I don't (as far as I can see) need to call any C code from C++, nor will I need to use C++ objects in my C code. Simple method calls passing arrays of doubles plus a few ints as arguments will be all that I need in terms of interaction from my main application an the C++ code.
From some quick googling, it seems that I can write a C++ interface module, which can then expose some c compatible functions that I can call to make use of freeverb3. I"ve written a micro example to see how this might work. For this example, I have a dummy c++ file called test.cpp:
#include <iostream>
using namespace std;
class test_class
{
int a;
public:
int get_a();
void set_a( int v );
};
int test_class::get_a()
{
return a;
}
void test_class::set_a( int v )
{
a = v;
}
static test_class *c;
extern "C"
{
void init();
void set( int v );
int get();
}
void init()
{
c = new test_class();
}
void set( int v )
{
c->set_a( v );
}
int get()
{
return c->get_a();
}
I have a dummy c file that calls the functions:
#include <stdio.h>
/* Forward declaratoins for extern "C" functions in C++ code */
void init();
int get();
void set( int v );
/* C language code that references functions in C++ code */
int main()
{
init();
set( 55 );
printf( "value: %d\n", get() );
set( get() + 12 );
printf( "value: %d\n", get() );
return 0;
}
And, I have a makefile that creates an executable.
test: test.o user.o
g++ -o test user.o test.o
test.o: test.cpp
g++ -c test.cpp
user.o: user.c
gcc -c user.c
Is this a good way of using C++ code from C? Is there a better/more sophisticated/more traditional way of achieving this aim?

You might want to think about it the other way.
Write your higher level application in C++, invoke the C++ library where you want without complications and call all your current C modules from the C++ level.
IMHO, this is easier to achieve than doing the same with C as high level.

If you intend to use more than one C++ object from C you need to pass an extra instance pointer (this) to the C wrapper functions:
struct A {
A();
~A();
void set(int);
};
The C wrapper:
extern "C"
{
struct A* a_create(void);
void a_destroy(struct A*);
void a_set(struct A*, int);
}
You may also like to catch all C++ exceptions in the C wrapper functions and convert them to error codes.

Pass a pointer to your object instead of using a static variable.
C++ class:
class Foo
{
public:
void doStuff();
};
Common include file:
#ifdef __cplusplus
extern "C"
{
#endif
void Foo_doStuff(void* handle);
void* Foo_create();
void Foo_destroy(void* handle);
#ifdef __cplusplus
}
#endif
Wrapper functions
void Foo_doStuff(void* handle)
{((Foo*)handle)->doStuff();}
void* Foo_create()
{return new(nothrow)Foo;}
void Foo_destroy(void* handle)
{delete (Foo*)handle;}

Not sure whether this goes from C to C++ but it is well worth looking into Swig

Make an extern "C" wrapper in C++, e.g.
// myWrapper.h
#ifdef __cplusplus
extern "C"
{
#endif
void func1(void);
int func2(void);
void func3(char const *str_ptr, size_t len);
#ifdef __cplusplus
}
#endif
// myWrapper.cpp
#include "myWrapper.h"
#include "your_cpp_library.h"
void func3(char const *str_ptr, size_t len)
{
std::string s(str_ptr, str_ptr + len);
call_cpp_function(s);
}
// etc.
In your C code you #include "myWrapper.h" and call those functions. Make sure that:
The code in myWrapper.h stays in the common subset of C and C++
You do not do any cross-boundary resource allocation
The latter might work but it's best to avoid it to be safe. The latter point means that if memory is to be allocated, it must be allocated and freed by the same side; e.g. you can't have the C++ side call malloc and give a pointer to the C side, and then have the C side call free. You have to pass the pointer back to whoever allocated it and let them free it.
Important: as Alf says in a comment, you must have main() in C++ and use the C++ linker , when doing C - C++ inter-linking. This is not a big hurdle though; you can rename your C code's main() function to main2(), and have the C++ code do extern "C" int main2(); and call it.

Related

How to create C API to C++ Function

I am learning how to generate an array of random numbers in C++. I am using a std::vector and std::generate (I'm trying to use modern idiomatic C++ - not sure how well I'm doing).
What I would like to do is to expose this function to plain old C code. How can make this function available from C?
Code below. Thanks!
void RandomArray(std::vector<double> &data)
{
std::random_device rd{};
auto mtgen = std::mt19937{ rd() };
auto ud = std::uniform_int_distribution<>{ 1, 6 };
auto gen = [&ud, &mtgen](){ return ud(mtgen); };
std::generate(data.begin(), data.end(), gen);
}
You can use the extern "C" statement to make the function linkable to C code.
But working from your C++ version to the C version is harder I think, it would go something like this:
void RandomArray(std::vector<double> &data)
{
std::random_device rd{};
auto mtgen = std::mt19937{ rd() };
auto ud = std::uniform_int_distribution<>{ 1, 6 };
auto gen = [&ud, &mtgen](){ return ud(mtgen); };
std::generate(data.begin(), data.end(), gen);
}
extern "C" void RandomArray(double* data, size_t size)
{
std::vector<double> v(size);
RandomArray(v);
std::copy(std::begin(v), std::end(v), data); // need to copy out
}
Personally I would go the other way and make the C version the main algorithm and get the C++ version to call that:
extern "C" void RandomArray(double* data, size_t size)
{
std::random_device rd{};
auto mtgen = std::mt19937{ rd() };
auto ud = std::uniform_int_distribution<>{ 1, 6 };
auto gen = [&ud, &mtgen](){ return ud(mtgen); };
std::generate(data, data + size, gen);
}
void RandomArray(std::vector<double>& data)
{
RandomArray(data.data(), data.size());
}
Also it would be a lot faster not to initialize the random generator each time you call the function. One way to do that is making the random generator static. If you need thread safety you could also make it thread_local:
extern "C" void RandomArray(double* data, size_t size)
{
thread_local static auto mtgen = std::mt19937{std::random_device{}()};
auto ud = std::uniform_int_distribution<>{ 1, 6 };
std::generate(data, data + size, [&ud](){ return ud(mtgen); });
}
While C++ has standard support to call C functions, the reverse is not true. The only way to call a C++ function from C code is to make it C-compatible and use the C++ facilities to call it as a C function (only the function internal body code is C++ code), and compile it with a C++ compiler, to produce a C++ object code that has a C entry point
mod.h
#ifdef __cplusplus
extern "C" {
#endif
void my_function(const char *sample_parameter1, const int sample_parameter2);
#ifdef __cplusplus
}
#endif
mod.cc
#include <iostream>
#include "mod.h"
void my_function(const char *sample_parameter1, const int sample_parameter2)
{
std::cout << sample_parameter1
<< ", "
<< sample_parameter2
<< std::endl;
}
And then
main.c
#include <stdlib.h>
#include "mod.h"
int main()
{
my_function("Sample literal 1", 37);
exit(EXIT_SUCCESS);
}
To compile this, you need the following sequence:
$ c++ -o mod.o -c mod.cc
$ cc -o main.o -c main.c
$ c++ main.o mod.cc
$ a.out
(You need to invoque c++ to make the link phase, as it needs to include the standard c++ modules required at link time)
As far as you have included a c++ module, the whole project must be considered a c++ project and not C, because you'll need the C++ runtime modules to initialize properly all the global c++ objects you declare in your c++ modules and to include the c++ libraries you may use. You'll only compile with the cc C compiler only the modules that are pure C (and you have to use the C++ rules to distinguish them as C code)
The c++ compiler uses a different naming procedure for identifiers and all the C identifiers must be marked extern "C" (that's the reason of the mod.h file) If you don't follow that you'll lead to a unknown function 'my_function' linker message because C++ names include information about the parameter list types used in them, to allow for overloaded function names.

Can we define a C++ method in a C file?

Assume that we have a C++ project. We can use a function which defined in a C file in the C++ project through extern "C" keyword. Example:
C code: cfile.c
#include <stdio.h>
void f(void)
{
printf("\n This is a C code\n");
}
Cpp Code: cppfile.cpp
#include <iostream>
extern "C" {
void f();
}
int main(void)
{
f();
return 0;
}
So, can we do that for the opposite case:
Cpp code: cppCode.cpp
struct MyClass
{
virtual void f(const char* text);
void func(const char* text);
};
Can we implement f method and func method in a C file (for instance: cCode.c) ??? Is that possible ? (Just the question for my personal purpose)
You can't do this directly. However, there is a workaround (of sorts). You can have a function with "C" linkage which returns the pointer to the object of the class - presumably dynamically allocated - converted to void*.
Than you can implement functions which would map to functions inside the class, but would take one additional argument - void*, which would be the address obtained from the call to creation function above. They would simply convert this void* to the type of the class and call it's member.
In the end, you'd need a dispose function which would corectly delete the pointer.

Wrap C++ namespaced enum to C interface

I'm trying to wrap an existing 3rd party C++ library to a C interface, so that it can be used in bindings for another language. I'm having trouble figuring out how to wrap a namespaced enum, as opposed to just redefining it:
// Existing C++ 3rd party library header
namespace foo {
enum Fruit {
APPLE = 0,
ORANGE
}
}
So then I have my wrapped.{h,cpp} with an extern "C" block, and I just can't figure out how to export the foo::Fruit enum into the C interface
// wrapped.h
#ifdef __cplusplus
extern "C" {
#endif
// I don't want to do this
typedef enum Fruit {
APPLE = 0,
ORANGE
} Fruit;
#ifdef __cplusplus
}
#endif
#endif
Is it possible to export (mirror) foo::Fruit from the C++ library into my C wrapper as Fruit?
edit: I just noticed that you wanted to wrap an existing library without modifying it.
I fear you are about out of luck then. In general there is just no way of extracting just the enum members out of C++ code without the C compiler choking.
In practice you've got the choice whether to programmatically translate your own set of enumerations into the C++ versions in the interface, try to mirror the C++ exactly and place a bunch of static assertions to double-check, or in theory even filtering them out through scripts.
There are simply no good options here I'm afraid. For the record I would tend to prefer the first of these bad options.
Personally I probably would be lazy and just stick to the C version.
Still, if required and the number of constants is large you can do a bit of macro magic to get a single definition with C-style "namespaces" as required.
First a single header defining all enum entries through a macro:
/* Fruit.h */
FOO_ENUM(APPLE) = 0,
FOO_ENUM(ORANGE)
Then in the C header:
/* C interface */
typedef enum {
# define FOO_ENUM(id) FOO_##id
# include "Fruit.h"
# undef FOO_ENUM
} Foo_Fruit_t;
And finally in the C++ header:
// C++ interface
namespace Foo {
enum Fruit_t {
# define FOO_ENUM(id) id
# include "Fruit.h"
# undef FOO_ENUM
};
}
There are many alternatives of course. For instance if you don't mind polluting the global namespace in C++ then can always define the full enumeration directly in the C interface and copy the individual enum members in the C++ version of the definition.
I ran into this particular problem with enums in a C wrapper for a C++ library recently and it caused quite a headache.
My solution is shown in the following mostly minimal working example but it is terribly inelegant in places. It is essentially a translation approach.
One must be wary not to declare anything twice with regard to the enums. The example passes int, a string or array of char and an enum.
A library header written in C++. This is the library that will be wrapped. MyClass.h:
#ifndef __MYCLASS_H
#define __MYCLASS_H
#include <iostream>
namespace MyNamespace {
using namespace std;
enum EnumControlInterface {HIDController=1, UVCController=2};
class MyClass {
private:
int m_i;
string m_text;
EnumControlInterface _controller;
public:
MyClass(int val);
~MyClass();
void int_set(int i);
void string_set(string text);
int int_get();
string string_get();
void writeEnum(EnumControlInterface MyInterface);
EnumControlInterface readEnum();
};
};
#endif
The C++ implementation of MyClass.cpp:
#include "MyClass.h"
namespace MyNamespace {
MyClass::MyClass(int val) {
cout << "MyClass is being created" << endl;
cout << "The parameter passed to the MyClass constructor is: " << val << endl;
}
MyClass::~MyClass() {
cout << "MyClass is being destroyed" << endl;
}
void MyClass::writeEnum(EnumControlInterface MyInterface) {
_controller = MyInterface;
cout << "The interface control Enum is set in MyClass.cpp as: " << _controller << endl;
}
EnumControlInterface MyClass::readEnum() {
return _controller;
}
void MyClass::string_set(std::string text) {
m_text = text;
}
string MyClass::string_get() {
return m_text;
}
void MyClass::int_set(int i) {
m_i = i;
}
int MyClass::int_get() {
return m_i;
}
}
A "C wrapper" header file MyWrapper.h which wraps MyClass.h:
#ifndef __MYWRAPPER_H
#define __MYWRAPPER_H
#ifdef __cplusplus
namespace MyNamespace {
extern "C" {
#endif
typedef enum WrapperEnumControlInterface {WrapHIDController=1, WrapUVCController=2} WrapperEnumControlInterface;
typedef struct MyClass MyClass;
MyClass* newMyClass(int val);
void MyClass_int_set(MyClass* v, int i);
int MyClass_int_get(MyClass* v);
void MyClass_string_set(MyClass* v, char* text);
char* MyClass_string_get(MyClass* v);
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface);
WrapperEnumControlInterface MyClass_readEnum(MyClass* v);
void deleteMyClass(MyClass* v);
#ifdef __cplusplus
}
}
#endif
#endif
The "C wrapper" implementation is written in a mixture of C and C++. Specifically the function definitions have to be C and the parameters passed and returned have to be C types as well. Inside the functions and inside the preprocessor areas __cplusplus C or C++ should be fine.
One can not, for example, ask a function inside the extern "C" block to accept the type std::string. It would defeat the objective of the wrapper: to expose only C code that operates the underlying C++ library. extern "C" determines what is exposed without name mangling (see questions about name mangling in C++). __cplusplus is defined by (many) C++ compilers.
MyWrapper.cc:
#include "MyClass.h"
#include "MyWrapper.h"
#include <vector>
namespace MyNamespace {
extern "C" {
MyClass* newMyClass(int val) {
return new MyClass(val);
}
void deleteMyClass(MyClass* v) {
delete v;
}
void MyClass_int_set(MyClass* v, int i) {
v->int_set(i);
}
int MyClass_int_get(MyClass* v) {
return v->int_get();
}
void MyClass_string_set(MyClass* v, char* text) {
//convert incomming C char* to a C++ string
string stringToSend = string(text);
cout << "the string received from the program by the wrapper is " << text << endl;
cout << "the string sent to the library by the wrapper is " << stringToSend << endl;
v->string_set(stringToSend);
}
char* MyClass_string_get(MyClass* v) {
string result = v->string_get();
cout << "the string received from the library by the wrapper is " << result << endl;
// Convert the C++ string result to a C char pointer and return it. Use vectors to do the memory management.
// A vector type of as many chars as necessary to hold the result string
static vector<char> resultVector(result.begin(), result.end());
cout << "the data in the vector who's pointer is returned to the program by the wrapper is: " << &resultVector[0] << endl;
return (&resultVector[0]);
}
void MyClass_writeEnum(MyClass* v, WrapperEnumControlInterface MyInterface) {
v->writeEnum((EnumControlInterface)MyInterface);
}
WrapperEnumControlInterface MyClass_readEnum(MyClass* v) {
EnumControlInterface result = v->readEnum();
return (WrapperEnumControlInterface)result;
}
}
}
A C program that calls the C++ library via the wrapper Cproject.c:
#include "MyWrapper.h"
#include "stdio.h"
int main(int argc, char* argv[]) {
struct MyClass* clsptr = newMyClass(5);
MyClass_int_set(clsptr, 3);
printf("The int read back in Cproject.c is: %i\n", MyClass_int_get(clsptr));
MyClass_writeEnum(clsptr, WrapUVCController);
printf("The enum read back in Cproject.c is: %d\n", MyClass_readEnum(clsptr));
MyClass_string_set(clsptr, "Hello");
char *textReadBack = MyClass_string_get(clsptr);
printf("The text read back in Cproject.c is: %s \n", textReadBack);
deleteMyClass(clsptr);
return 0;
}
And just for completeness a C++ project that calls the C++ library directly without the use of the wrapper CPPProgram.cpp, so short!:
#include "MyClass.h"
#include <iostream>
using namespace std;
using namespace MyNamespace;
int main(int argc, char* argv[]) {
MyClass *c = new MyClass(42);
c->int_set(3);
cout << c->int_get() << endl;
c->writeEnum(HIDController);
cout << c->readEnum() << endl;
c->string_set("Hello");
cout << c->string_get() << endl;
delete c;
}
The MyClass C++ class is compiled to a static library, the wrapper is compiled to a shared library there is no particular reason, both could be static or shared.
The C program that calls the wrapper library (Cproject.c) must be linked with a C++ compiler (G++ etc.)
Obviously this example doesn't have a serious application. It is based on https://www.teddy.ch/c++_library_in_c/ in terms of structure but with the enum bits added in.
Often the person writing the wrapper doesn't have access to the source code of the library they're trying to wrap (MyClass.cpp in this case) they will have the .so or .dll or .a or .lib for Linux and Windows shared and static libraries respectively. It is not necessary to have the source code for the C++ library. Only the header file(s) for the C++ library are needed to write an effective wrapper.
I have written this out partly to provide a more verbose answer to the original question, one that can be copied compiled easily and played around with but also because this is the only way I have been able to solve the problem so far and it is not satisfactory in my view. I would like to be able to wrap the enums in the same way one wraps the public member functions not re-create the enums inside the wrapper with slightly different names.
Sources of related information that proved useful:
https://www.teddy.ch/c++_library_in_c/
How to cast / assign one enum value to another enum
Developing C wrapper API for Object-Oriented C++ code
Converting a C-style string to a C++ std::string
Returning pointer from a function
std::string to char*
Of course all unsafe, wrong etc. coding practices are my fault entirely.

Including C-DLL from C++

This feels like a noob question, so if it's a dupe, please point me to the right location :)
I tried including a DLL written in C into a C++ program. It didn't work; gcc said
test.cpp: xxx: error: too many arguments to function.
Here's a minimal working example:
Wrapper for DLL functions:
/* myWrapper.h */
#ifndef _MYWRAPPER_H
#define _MYWRAPPER_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers();
#ifdef __cplusplus
}
#endif
#endif
Implementation thereof:
/* myWrapper.c */
#include <windows.h>
#include "myHeader.h"
#ifdef __cplusplus
extern "C" {
#endif
HINSTANCE drvsHANDLE;
extern FARPROC EXPORTED_functionNameP;
int GetDLLpointers()
{
static int result;
drvsHANDLE = LoadLibrary("myLibrary.dll");
if (drvsHANDLE == NULL) return (result=0);
EXPORTED_functionNameP = GetProcAddress(
drvsHANDLE, "originalFunctionName");
if (EXPORTED_functionNameP == NULL) return (result = 0);
return (result = 1);
}
#ifdef __cplusplus
}
#endif
Naturally, I haven't written these nor the library myself, and preferably, they should all stay untouched. I did however add the extern "C" lines.
Then, my main file:
// my Main
#include <windows.h>
#include "myHeader.h"
int main(int argc, char **argv)
{
int arg = 1;
EXPORTED_functionNameP(arg);
return 0;
}
Build commands:
gcc -I. -c -o myHeader.o myHeader.c -L. -lmyLibrary
g++ -I. -o main.exe myMain.cpp myHeader.o -L. -lmyLibrary
It works fine if I rewrite my main.cpp into valid C and compile with gcc instead of g++.
I tried changing extern "C" into extern "C++" to no avail, I tried all permutations or gcc and g++ for the two build commands, nothing.
I know it's something to do with name mangling, but I thought gcc would take care of that when you include the extern "C" lines...Can someone please explain what I'm missing here?
In case it matters --
Windows XP Pro (will be Win7 later on)
(MinGW) gcc 4.6.2
I know this is a very old question, but I am having exactly the same issues but in relation to writing a generic wrapper template for wrapping calls to LoadLibrary() and GetProcAddress()
Taking https://blog.benoitblanchon.fr/getprocaddress-like-a-boss/ as inspiration, it looks like he is taking FARPROC as a kind of "void* for Windows functions" and then casting it to the correct type subsequently.
I needed to tweak that code a little to work for me, and reproduce it here:
class ProcPtr
{
public:
explicit ProcPtr(FARPROC ptr) : m_ptr(ptr) {}
template <typename T>
operator T* () const { return reinterpret_cast<T*>(m_ptr); }
private:
FARPROC m_ptr;
};
class DllHelper
{
public:
explicit DllHelper(LPCTSTR filename) : m_module(LoadLibrary(filename)) {}
~DllHelper() { FreeLibrary(m_module); }
ProcPtr operator[](LPCSTR proc_name) const
{
return ProcPtr(::GetProcAddress(m_module, proc_name));
}
private:
HMODULE m_module;
};
So, with that helper code now available we can use it to write a wrapper class that encapsulates several functions in the Advapi32 library:
class Advapi32
{
public:
Advapi32() : m_dll(TEXT("Advapi32"))
{
getUserName = m_dll["GetUserNameA"];
openSCManager = m_dll["OpenSCManagerA"];
bogusFunction = m_dll["BogusFunctionThatDoesNotExist"];
}
decltype(GetUserNameA)* getUserName;
decltype(OpenSCManagerA)* openSCManager;
decltype(GetWindowsDirectoryA)* bogusFunction;
private:
DllHelper m_dll;
};
bogusFunction is a function with the same signature as GetWindowsDirectoryA but which doesn't exist in Advapi32. This is what I was trying to achieve - graceful fallback on an older OS which might not have a certain function.
So, finally a test app...
int main()
{
Advapi32 advapi32;
auto func1 = advapi32.getUserName;
if (func1)
{
TCHAR infoBuf[256];
DWORD bufCharCount = sizeof(infoBuf);
if (func1(infoBuf, &bufCharCount))
{
std::cout << "Username: " << infoBuf << std::endl;
}
}
auto func2 = advapi32.openSCManager;
if (func2)
{
SC_HANDLE handle = func2(NULL, NULL, SC_MANAGER_CONNECT);
if (handle)
{
std::cout << "opened SC Manager" << std::endl;
}
}
auto func3 = advapi32.bogusFunction;
if (func3)
{
std::cerr << "This should not happen!" << std::endl;
}
else
{
std::cout << "Function not supported" << std::endl;
}
}
Output:
Username: TestAccount
opened SC Manager
Function not supported
Note: This was compiled as a Windows 32-bit console application with MBCS rather than Unicode, under VS2019 with the VS2015_XP toolset, since that is what I am needing to target (don't ask).
The FARPROC type is a function pointer for a function that takes no parameters. You should declare EXPORTED_functionNameP like so (replacing void with whatever the function really returns):
extern void (*EXPORTED_functionNameP)(int);
And initialize it like so (the returned value from GetProcAddress() pretty much always needs to be cast to the correct type):
EXPORTED_functionNameP = (void (*)(int)) GetProcAddress(drvsHANDLE, "originalFunctionName");
A typedef for the funciton type might make things a bit more readable.
There is a difference between C and C++.
int (FAR WINAPI * FARPROC) ()
In C, the FARPROC declaration indicates a callback function that has an unspecified parameter list. In C++, however, the empty parameter list in the declaration indicates that a function has no parameters.
The MSDN page on CallWindowProc explains a bit more.
After a quick Google search, it seems that FARPROC is defined as this:
typedef int (FAR WINAPI *FARPROC)();
That is, FARPROC is a function that returns an int and takes no arguments. So you can't use it for any other case.
Instead declare EXPORTED_functionNameP like this:
extern void (*EXPORTED_functionNameP)(int);
Now EXPORTED_functionNameP is a pointer to a function that takes an int argument and returns no value.
It is because of FARPROC is defined as:
int (FAR WINAPI * FARPROC) ()
So you can not pass any parameters to such function in C++. For fix it you should define EXPORTED_functionNameP as pointer to function with equal semantics as defined in DLL-library. For example:
typedef (void* EXPORTED_functionNameP)(int value);
EXPORTED_functionNameP ExportedFns;
...
ExportedFns = GetProcAddress(drvsHANDLE, "originalFunctionName");
FARPROC is defined as
typedef int (FAR WINAPI *FARPROC)();
When you pass an additional argument although the argument list of the prototype is empty you get the error.
You need a proper prototype definition for PORTED_functionNameP and cas the result from GetProcAddress to that type in your GetDLLPopinters functions.

How to export C++ functions with GCC?

I'm using Code::Blocks to compile a shared library on Ubuntu. When I make a simple main.c file with:
void* CreateInterface()
{
int* x = (int*)malloc( sizeof( int ) );
*x = 1337;
return x;
}
This works fine and I can find the function CreateInterface with dlsym in another application. However, I want the function to create an instance of a class written in C++. I tried the following:
#include "IRender.h"
extern "C"
{
void* CreateInterface()
{
return new Flow::Render::IRender();
}
}
This compiled fine, but now my other application fails to find CreateInterface. How should I deal with this?
I've solved the problem by making a .cpp file with the declaration:
extern "C" void* CreateInterface()
{
return new Flow::Render::IRender();
}
and a .c file with the header like this:
extern void* CreateInterface();