A little background:
I've got a library of C code that is part of larger system (all C). For this particular part of the C library a GUI has to be created which allows users to play around with the options. For the GUI I've chosen QT, since cross-platform support is desired.
I'm using Eclipse and MinGW as IDE and compiler (but I think the question is more language than compiler specific?).
With QT I've created a widget that holds a pointer to a struct implemented in C that contains pointers to several functions that perform the logic of the C library.
//QTWidget.cpp
extern "C" {
#include "c-src/CLogic.h"
//extern char* textHelper;
}
QTWidget::QTWidget(QWidget *parent)
{
//rtw is a struct that contains a function pointer to a member of QTWidget
this->rtw.displayText = &QTWidget::displayText;
this->clogic = CLogic_getInstance(&rtw);
}
//Public SLOT, connected to a button's clicked SIGNAL
void QTWidget::buttonClicked()
{
this->clogic->buttonClicked();
}
void QTWidget::displayText(char *text, int position)
{
//I've tried creating a QString from the char*, but this does not work at all.
//ui.textItem->setText(textHelper);
ui.textItem->setText(text);
}
When the user presses a button in the GUI, the method QTWidget::buttonClicked() is called, which tells the C library to do something. Note the the CLogic struct has a reference to the the QTWidget in the form of a struct RefToWidget which holds a function pointer.
//CLogic.c
static CLogic instance;
void CLogic_buttonClicked()
{
//I've tried several variants here, such as making a global
//char* textHelper = "Hello World";
//that is referenced by using the "extern" keyword in the CPP file above.
instance.rtw->displayText("Hello World", 1);
}
CLogic* CLogic_getInstance(RefToWidget *rtw)
{
instance.rtw = rtw;
instance.buttonClicked = &CLogic_buttonClicked();
}
When debugging this program, I find that all the function calls are executed as intended (when I press a button, the QT slot buttonClicked() is called, the CLogic_buttonClicked() is called, which calls the QTWidget::displayText() as planned, but in this last call the parameters are invalid. The char* text points to 0x1 and claims to be pointing to memory out of bounds, while the int position looks like some random number (uninitialized).
How do I pass this data from C to CPP?
EDIT #Luccas Matteis:
#ifdef __cplusplus
#include "QTWidget.h"
extern "C" {
#endif
struct RefToWidget{
#ifdef __cplusplus
void (QTWidget::*displayLine)(char* text, int lineNumber);
#else
void (*displayLine)(char* text, int lineNumber);
#endif
};
typedef struct RefToWidget RefToWidget;
#ifdef __cplusplus
}
#endif
As said above the function calls behave as expected, but the data is not passed "correctly" (even though that when I look at it, the code seems a bit... weird... ;))
Your problem is not passing the char * from C to C++ but calling a C++ function from C. I presume that CLogic.c is compiled as a C library? If not, can you rename it to CLogic.cpp or use a compiler switch to force it to be compiled as C++ even though it has a C file extension?
If you want a C++ GUI on a C library/system, you need to use proper Model-View-Controller logic. Here the C++ code is the View and the Controller while the C code is the Model (as best as I can tell from your description). You need to make it so you set and get data from the model but the model never calls the View or Controller as you are trying to do.
Think about what you are REALLY trying to do. If you just want to display a static string when the button is pressed, why go to the bother of calling into CLogic.c? If you want to display a string that depends upon the state of the CLogic instance then instead do something like:
void QTWidget::buttonClicked()
{
char *display_text = this->clogic->get_button_click_text();
ui.textItem->setText(display_text);
}
I guess the problem is that the structure holds a pointer to a member function. The member function probably expects the first parameter to be 'this' - the object it refers to. So, in fact what you are seeing in debug as text is the second parameter.
A 'solution' would probably be to do something like "instance.rtw->displayText(instance.rtw, "Hello World", 1)", but have no idea if it is portable etc.
Edit: Saying it explicitly: the 'solution' stated above is just to try and check if this is the problem. As the comments are saying this is a horrible hack that might not work even on the same compiler.
I don't think that you should call a C++ method from C. Normally you need to go through a static method that dereferences a pointer argument
Related
I have a C program which I need to connect to a C++ API. I asked on here and was given great advice, leading to creating a "wrapper".
So, in the API there is a type called "APIName::ReturnCode", and I wanted to create a C equivalent, so I've done the following:
In c_api.h:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* API_ReturnCode_t;
EXTERNC API_ReturnCode_t api_returncode_init();
EXTERNC void api_returncode_destroy(API_ReturnCode_t rc);
#undef EXTERNC
in c_api.cpp:
#include "c_api.h"
#include "/path/to/api/api.h"
API_ReturnCode_t api_returncode_init() {
return new APIName::ReturnCode;
}
void api_returncode_destroy(API_ReturnCode_t untyped_ptr) {
APIName::ReturnCode* typed_ptr = static_cast< APIName::ReturnCode*>(untyped_ptr);
delete typed_ptr;
}
So I compile that into a library and include it in my main program, and I can use things like:
API_ReturnCode rc;
to define a variable.
However, my next issue is how to define enumerated types in a similar way. So, the api has the following definition for error codes:
namespace APIName {
typedef enum ReturnCode_enum ReturnCode;
enum ReturnCode_enum {
RC_OK , // success
RC_ERROR , // general error
RC_NOT_AVAILABLE , // feature is not available
};
}
How do I recreate this in my wrapper so that I can do something like this in my code:
API_ReturnCode rc = API_RC_OK;
Thank you.
So after some clarification, my original answer is no longer applicable -- but is still retained below this answer.
Since the original C++ API cannot be altered in any way, you are much more limited in your available options.
You want to be able to do:
API_ReturnCode rc = API_RC_OK;
But rc is an opaque type (void*) that requires being destroyed with api_returncode_destroy -- so this won't be possible in an easy and sane way (not without confusing who owns the API_RC_OK calls). The biggest issue is that if we could produce an API_RC_OK instance, it leads to questionable ownership. For example:
API_ReturnCode rc = API_RC_OK;
api_returncode_destroy(rc); // is this good? is 'API_RC_OK' a resource that needs deleting?
And it gets more confusing in more complicated expressions.
Since the APIName::ReturnCode_enum type is just a classic C-style enum, which is implicitly convertible to an int, your best-bet here would be to try to preserve the int-like property by making API_ReturnCode_t's definition be:
typedef int API_ReturnCode_t;
Then any of the C++-wrapped calls can propagate the values as this int
Unfortunately to be able to receive these values on the other side, you will need to duplicate some effort here by manually re-creating these constants in some way. There are a few approaches that come to mind, all with pros and cons.
The inconvenient truth here is that, because you're trying to expose values defined in C++ in C, you'll need to somehow re-encode this on the other side in some way. You can't simply include the C++ header and use it in C, since they are different languages and C++ contains features that C doesn't understand.
1. Use extern constants
One possible approach is to use extern const values that get defined in the source from the underlying values, so you aren't stuck duplicating the values themselves. For example:
c_api.h
EXTERNC extern const API_ReturnCode_t API_RC_OK;
EXTERNC extern const API_ReturnCode_t API_RC_ERROR;
EXTERNC extern const API_ReturnCode_t API_RC_NOT_AVAILABLE;
c_api.cpp
extern "C" {
const API_ReturnCode_t API_RC_OK = APIName::RC_OK;
const API_ReturnCode_t API_RC_ERROR = APIName::RC_ERROR;
const API_ReturnCode_t API_RC_NOT_AVAILABLE = APIName::RC_NOT_AVAILABLE;
} // extern "C"
The good thing with this approach is that you aren't stuck manually setting API_RC_OK to 0, and API_RC_ERROR to 1, etc -- so these values are not strongly coupled.
The thing to watch out for is that these extern constants would not be (safely) usable from other objects during static initialization, since it's not guaranteed when these values will be set. If you aren't doing much static initialization, this shouldn't be of any concern.
2. Just duplicate the effort
If the enum is not large, and not likely to grow much larger, the obvious simple approach is to just do:
#define API_RC_OK 0
#define API_RC_ERROR 1
#define API_RC_NOT_AVAILABLE 2
or some equivalent thereof. The pro is that this can be used anywhere, compared to extern constants. The obvious con here is that the wrapper is strongly coupled to the wrapped library. If this is a large enumeration, or an enum that is likely to change often / regularly -- this is approach is probably not the best.
3. Define a possibly-orthogonal enumeration
One other option is to define an orthogonal enumeration instead. This requires re-defining the enum cases that you care about, and translating them through a separate function call. This results in more effort -- so depending on what you're doing, this may not be the best case.
c_api.h
typedef enum {
API_RC_OK,
API_RC_ERROR,
API_RC_NOT_AVAILABLE,
/* other states? */
} API_ReturnCode_t;
**c_api.cpp
API_ReturnCode_t to_return_code(APIName::ReturnCode rc)
{
switch (rc) {
case APIName::RC_OK: return API_RC_OK;
case APIName::RC_ERROR: return API_RC_ERROR;
case APIName::RC_NOT_AVAILABLE: return API_RC_NOT_AVAILABLE;
}
return API_RC_NOT_AVAILABLE;
}
In your wrapper code, anywhere you receive an APIName::ReturnCode you would now translate to an API_ReturnCode_t before returning back to the C caller.
The nice thing about this approach is that the enumerators no longer need to be in-sync, and that you can restrict the enum cases that you want to abstract out (assuming you don't want 1-1 mapping).
This also presents an easier way to upgrade in the future to different versions of the C++ library, since everything is internalized by the translation function. If the C++ library introduces new states, you can choose to coalesce some of those values together in a way that may make it more consumable by the C client.
The obvious downside with this approach is that it takes more work, since you're defining a separate hierarchy and a translation system that will be quite similar in the beginning. It's more work up-front for a higher return later on.
Old Answer
There is nothing specific to C++ about your ReturnCode_enum class. It's actually written in a more legacy-C++ style (e.g. not using enum class for scoping), which makes it usable in C directly.
So why not define the enum in the c_api.h header file instead, and use it in your C++ as well? This may require changing your opaque handle definition depending on what is stored in it; but this way you would have exactly 1 definition of the enumeration.
You can bring the C symbol into C++ namespaces using either typedef or using aliases, which allow a more C++-esque discovery of the values.
In c_api.h:
enum Api_ReturnCode_enum {
RC_OK , /* success */
RC_ERROR , /* general error */
RC_NOT_AVAILABLE , /* feature is not available */
};
/*
or 'typedef enum { ... } Api_ReturnCode_enum;' if you want don't want to specify
'enum' every time in C
*/
In your C++ API:
#include "c_api.h"
namespace APIName { // bring it into this namespace:
// Alias the "Api_" prefixed enum to be more C++ like
typedef Api_ReturnCode_enum ReturnCode;
// alternative, in C++11 or above:
// using ReturnCode = Api_ReturnCode_enum;
}
I wouldn't hide error code enums in opaque handles.
Create a new enum and convertion functions in the c_api.cpp file
c_api.h
typedef enum {
RC_OK,
RC_ERROR,
RC_NOT_AVAILABLE
} ReturnCode_copy;
ReturnCode_copy some_function(...);
c_api.cpp
static ReturnCode_copy convert(APIName::ReturnCode code) {
switch(code) {
//return correct ReturnCode_copy
}
}
ReturnCode_copy some_function(...) {
auto code = //some api function returning error code
return convert(code);
}
or you could be naughty and just copy the values directly in your new enum and just static_cast directly without the convert function.
I'm trying to make some sort of C++ "bridge" to connect an unmanaged C++ dll on one end (without modifying their code) to a C# Wrapper which uses DllImport for various imports.
I was able to pass a C# string to my bridge using char pointers, but the receiving Dll needs to receive std::string, so I tried with std::string(foo); with no luck, it always gets transformed into weird characters.
The structure is the following :
C# Wrapper
[DllImport(#"Bridge.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void initDetector(string foo, int something = 0);
C++ Bridge
extern "C" __declspec(dllexport) void initCppClass(char* foo, int something)
{
std::string bar = std::string(foo);
std::cout << bar << std::endl; //Returns "foo"
instance = new CppClass(bar, something);
}
C++ Imported DLL (not allowed to change code here)
CppClass::CppClass(std::string foo, int something)
{
std::cout << foo << std::endl; //Returns garbage
}
Note that this constructor is for demonstration purposes only, as I cannot disclose the original code.
I originally tried passing the char* directly to the constructor but that didn't work either. Is there something I'm missing here ?
I think the problem is different string encoding.
Try adding CharSet = CharSet.Ansi in C#, like this:
[DllImport(#"Bridge.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
However, please read the documentation of that C++ dll API. A lot of C++ code, especially if that’s cross-platform code, expect UTF8-encoded strings. If that’s your case, instead change the bridge to
extern "C" __declspec(dllexport) void initCppClass(const wchar_t* foo, int something)
And write code to convert the string from UTF16-encoded C pointer into UTF8-encoded std::string, see this answer for an example.
Update: another possible reason is different STL, or different CRT. When you pass std::string or any other STL objects objects across DLL boundaries, you have to use same compiler & same version of it, same build settings for (e.g. in VC++, std::strings memory layout differs between debug and release builds), and also both DLLs must link to CRT dynamically., e.g. Multi-threaded DLL (/MD)
I am experiencing the following issue, in my DLL project:
At the DLL side :
Inside the DLL I have declared a static vector as follows :
static std::vector<FilterProcessor::FilterInfo*> TableOfContents;
At DLL’s initialization time of static members, I am adding some entries to the above vector.
I have defined an extern “C” global function (getTocPointer()) which is returning a pointer to the vector, when it called from the client program.
extern "C" __declspec(dllexport) std::vector<FilterProcessor::FilterInfo*>* __cdecl getLibraryTOC();
At the client’s program side :
The DLL library is loaded without any problem
The address of getTocPointer() function is returned correctly to the client program, when the getProcAddress() function is called.
Indeed, when I am performing the debugging process in the DLL-side, the client program calls the above function and the execution process enters to it.
However, the vector has a zero size and, has no any contents which were added to it at initialization time. It seems it points to another vector object. . .
I can’t really understand what exactly goes wrong here.
The way of adding entries to this vector at initialization time, is the proper way?
If yes, what probably goes wrong when the client program calls the getLibraryTOC() function?
Thanks in advance
George
If that static global definition of the vector appears in a header file, then yes you do have multiple different vectors. Change the keyword static to extern to make the header file declare the vector rather than defining it, and then add exactly one definition in an implementation file.
Then, you may encounter the static initialization order fiasco. If the vector is defined in a different compilation unit than the code attempting to add entries to it, there's no guarantee that the vector object is alive yet. Attempting to use a vector whose constructor hasn't run is undefined behavior -- it might easily manifest as the constructor running afterward and setting the contents to zero length (as a default constructor should), but many other problems are possible.
You can avoid the SIOF by using a local static.
std::vector<FilterProcessor::FilterInfo*>& table_of_contents()
{
static std::vector<FilterProcessor::FilterInfo*> singleton;
return singleton;
}
In every location that would have accessed the global, including the initialization logic that fills the vector, and also your getLibraryTOC() exported function, call the accessor function instead.
That all is applicable to any C++ software having multiple compilation units. When you have a DLL, things get even more complicated, because the DLL and EXE are compiled and linked separately from each other, possibly with different settings, different compilers, or even entirely different languages. Sharing of complex objects across DLL boundaries is real trouble. If the DLL and EXE are always recompiled at the same time, it can work. But if you're trying to distribute the DLL for use by another party who writes the EXE code, the strong coupling will quickly become intolerable.
A better approach is to hide the library objects from the DLL boundary, and pass only primitive or OS-managed types across. For example:
#define DLLAPI __declspec(dllexport) __cdecl
extern "C" DLLAPI int32_t getLibraryTocCount()
{ return table_of_contents.size(); }
extern "C" DLLAPI BSTR getLibraryTocName(int index)
{ return ::SysAllocString(table_of_contents[index].name.c_str(); } // assumes std::wstring
// etc
The library I have implemented contains the following code (in a brief description) :
An Index class which implements the Table of contents of the library
A collection of audio filters named Filter01, Filter02 etc.
Index.h
struct LIB_SPECS Library_TableOfContents
{
static bool addTOCEntry(FilterInfo* Filter_Info); // add an entry to the TOC
static std::vector<FilterInfo*> TableOfContents; // TOC
};
/*-------------------------------------------------------------------
Called from the client program to return the pointer to TOC */
extern "C" LIB_SPECS std::vector<FlterInfo*>* __cdecl getLibraryTOC();
Index.cpp
/* Define / Initialize static variables */
std::vector<FilterInfo*> Library_TableOfContents::TableOfContents = {};
//=====================================================================
bool Library_TableOfContents::addTOCEntry(FilterInfo* Filter_Info)
{
Library_TableOfContents::TableOfContents.push_back(Filter_Info);
return false;
}
//======================================================================
std::vector<FilterInfo*>* getLibraryTOC()
{
return &Library_TableOfContents::TableOfContents;
}
For each Audio Filter in the library :
Filterxx.h
class LIB_SPECS Filterxx
{
public:
static struct FilterInfo
{
public:
std::string filterName;
std::string filterDescription;
// other filter info
FilterInfo(); // FilterInfo constructor
} Filter_Info;
virtual String doSomeWork(int AvatarId);
virtual void deleteFilter() = 0;
};
Filterxx.cpp
Filterxx::FilterInfo Filterxx::Filter_Info("Filterxx", “A filter description e.g. Low pass Filter ” ); //
FilterInfo::FilterInfo(std::string name, std::string description)
{
Filter_Info.filterName = name;
Filter_Info.filterDescription = description;
Library_TableOfContents::addTOCEntry(&Filter_Info);
}
// other filter functions
The getLibraryTOC() function, is called from the client program to get the table of contents in order to show it to the user.
As I said, indeed it is called by the client but, at the time of call, the table of contents seems to have a zero size.
Consider the following code:
file_1.hpp:
typedef void (*func_ptr)(void);
func_ptr file1_get_function(void);
file1.cpp:
// file_1.cpp
#include "file_1.hpp"
static void some_func(void)
{
do_stuff();
}
func_ptr file1_get_function(void)
{
return some_func;
}
file2.cpp
#include "file1.hpp"
void file2_func(void)
{
func_ptr function_pointer_to_file1 = file1_get_function();
function_pointer_to_file1();
}
While I believe the above example is technically possible - to call a function with internal linkage only via a function pointer, is it bad practice to do so? Could there be some funky compiler optimizations that take place (auto inline, for instance) that would make this situation problematic?
There's no problem, this is fine. In fact , IMHO, it is a good practice which lets your function be called without polluting the space of externally visible symbols.
It would also be appropriate to use this technique in the context of a function lookup table, e.g. a calculator which passes in a string representing an operator name, and expects back a function pointer to the function for doing that operation.
The compiler/linker isn't allowed to make optimizations which break correct code and this is correct code.
Historical note: back in C89, externally visible symbols had to be unique on the first 6 characters; this was relaxed in C99 and also commonly by compiler extension.
In order for this to work, you have to expose some portion of it as external and that's the clue most compilers will need.
Is there a chance that there's a broken compiler out there that will make mincemeat of this strange practice because they didn't foresee someone doing it? I can't answer that.
I can only think of false reasons to want to do this though: Finger print hiding, which fails because you have to expose it in the function pointer decl, unless you are planning to cast your way around things, in which case the question is "how badly is this going to hurt".
The other reason would be facading callbacks - you have some super-sensitive static local function in module m and you now want to expose the functionality in another module for callback purposes, but you want to audit that so you want a facade:
static void voodoo_function() {
}
fnptr get_voodoo_function(const char* file, int line) {
// you tagged the question as C++, so C++ io it is.
std::cout << "requested voodoo function from " << file << ":" << line << "\n";
return voodoo_function;
}
...
// question tagged as c++, so I'm using c++ syntax
auto* fn = get_voodoo_function(__FILE__, __LINE__);
but that's not really helping much, you really want a wrapper around execution of the function.
At the end of the day, there is a much simpler way to expose a function pointer. Provide an accessor function.
static void voodoo_function() {}
void do_voodoo_function() {
// provide external access to voodoo
voodoo_function();
}
Because here you provide the compiler with an optimization opportunity - when you link, if you specify whole program optimization, it can detect that this is a facade that it can eliminate, because you let it worry about function pointers.
But is there a really compelling reason not just to remove the static from infront of voodoo_function other than not exposing the internal name for it? And if so, why is the internal name so precious that you would go to these lengths to hide that?
static void ban_account_if_user_is_ugly() {
...;
}
fnptr do_that_thing() {
ban_account_if_user_is_ugly();
}
vs
void do_that_thing() { // ban account if user is ugly
...
}
--- EDIT ---
Conversion. Your function pointer is int(*)(int) but your static function is unsigned int(*)(unsigned int) and you don't want to have to cast it.
Again: Just providing a facade function would solve the problem, and it will transform into a function pointer later. Converting it to a function pointer by hand can only be a stumbling block for the compiler's whole program optimization.
But if you're casting, lets consider this:
// v1
fnptr get_fn_ptr() {
// brute force cast because otherwise it's 'hassle'
return (fnptr)(static_fn);
}
int facade_fn(int i) {
auto ui = static_cast<unsigned int>(i);
auto result = static_fn(ui);
return static_cast<int>(result);
}
Ok unsigned to signed, not a big deal. And then someone comes along and changes what fnptr needs to be to void(int, float);. One of the above becomes a weird runtime crash and one becomes a compile error.
I'm having some trouble making a callback wrapper class method that needs to be used by a third party library; the JackAudio library.
I have been able to make a wrapper for a JackAudio callback function that needs two arguments.
I'm just having trouble creating a callback function for a particular function that needs a const char * as an argument.
So far I have been able to make the JackAudio library jack_set_sample_rate_callback function use a custom class and can be executed like so:
SoundClass Sound;
SoundClass * SoundPointer = &Sound;
jack_set_sample_rate_callback(
client,
SoundClass::SampleRateCallbackWrapper,
SoundPointer
);
And the class looks something like this:
SoundClass
{
int SampleRateCallback( jack_nframes_t nframes )
{
//executes some code when called.
}
static int SampleRateCallbackWrapper( jack_nframes_t nframes, void * arg )
{
return static_cast < SoundClass* > ( arg )->SampleRateCallback( nframes );
}
};
All of the above works well, with no issues.
The problem I'm having now is with the JackAudio callback function jack_set_error_function
This is what I tried:
static void ErrorCallbackWrapper( const char * arg )
{
return static_cast < SoundClass*>( arg )->SomeErrorFunction();
}
But I get error: invalid static_cast from type ‘const char*’ to type ‘SoundClass*’
I get the gist why this is happening, I just have no idea what to do for a solution.
Thanks in advance for any help guys.
Assuming the Jack API is written for the C language, there is a formal problem already with the working callback that you have. Namely that it then needs to be extern "C", and that as a static member function it cannot be. So formally it needs to be a free-standing function.
The documentation that you link to for the jack_set_error_function gives this signature, presumably expressed in C:
void jack_set_error_function( void(*)(const char *) func);
For C++ the callback must be assumed to be extern "C", so,
extern "C" void MyErrorFunction( char const* errorMessage )
{
// Whatever, e.g. post a message to the GUI event queue, or terminate.
}
If you want this function to in turn call a method on an object, then unless the library provides some special mechanism to help you, you will just have to use one of the following techniques:
a namespace scope variable accessed by the callback, or
a dynamically generated callback.
C++ does not as of yet support the second approach, at all, so the first one is strongly indicated – if you want a callback on a method of an object.
EDIT: Sorry, I forgot to mention,
the function declarations in the API documentation are syntactically invalid.
E.g. the documentation’s signature
void jack_set_info_function( void(*)(const char *) func );
simply won’t compile with a standard-conforming compiler. Not as C, and not as C++. It’s syntactically invalid in both languages.
Instead it should be
void jack_set_info_function( void(*func)(const char *) );
Since the documentation apparently is generated by DOxygen, it stands to reason that it's been generated from source code that compiles. If so then this is a bug in DOxygen, and a problem with the quality assurance of the library provider. However it might be a problem that lies solely with the library provider, or, I might be mistaken in the assumption that this is a C library?