I am writing an adapter to combine two APIs (one in C and another in C++).
If a function is called on the one API I need to pass the callers ID and the function's arguments to an adapter and call the according function with this information passed.
Now aparently they can not be mapped directly as one interface requires C++ compilation and the name mangling would screw the other so that is why I am using a set of adapters in the first place.
As the number of arguments varies, I looked up variadic functions and found the idea pretty useful, however I am operating on POD only and have to deal with structs, enums and a lot of different arguments per call, which might need to be put back into a struct before feeding it to the target function.
Every example I stumbled upon was far simpler and involved mostly arithmetic operations like summing stuff up , finding largest numbers or printing. Mostly done with for loops on the var_list.
Maybe I got stuck on the idea and it won't work at all, but I am just curious...
Say I wanted to assign the arguments from the list to my target functions parameters (the order of the arguments passed is the correct one), what would be a good way?
BOOL Some_Function(
/* in */ CallerId *pObjectId,
/* in */ someDataType argument1 )
{
BOOL ret = Adapter_Call(pFunction, pObjectId, argument1);
return ret;
}
and so once I made it to the right adapter I want to do
BOOL Adapter_Call(*pFunction, *pObjectId, argument1, ...)
{
va_list args;
va_start(args, argument1);
/*go over list and do `var_list[i] = pFunctionArgList[i]` which is
of whatever type so I can use it as input for my function */
va_end(args);
pObjectId.pFunction(arg1,...,argn);
}
Can I access the input parameters of a function to perform assignments like this?
Has anyone done something like this before? Is there a conceptual mistake in my thinking?
All I found on the net was this, http://www.drdobbs.com/cpp/extracting-function-parameter-and-return/240000586but due to the use of templates I am not sure if it wouldn't create another problem and so in the end implementing an adapter for each and every single functioncall may be simpler to do.
A SO search only returned this: Dynamic function calls at runtime (va_list)
First, you should heed Kerrek's advice about extern "C". This is C++'s mechanism for giving an identifier C linkage, meaning that the name won't be mangled by the C++ compiler.
Sometimes, and adapter still needs to be written for a C++ interface, because it manipulates objects that do not map to a C POD. So, the adapter gives the C interface a POD or opaque pointer type to manipulate, but the implementation of that interface converts that into an C++ object or reference and then calls the C++ interface. For example, suppose you wanted to provide a C interface for C++ std::map<int, void *>, you would have a common header file in C and C++ that would contain:
#ifdef __cplusplus
extern "C" {
#endif
struct c_map_int_ptr;
// ...
// return -1 on failure, otherwise 0, and *data is populated with result
int c_map_int_ptr_find (struct c_map_int_ptr *, int key, void **data);
#ifdef __cplusplus
}
#endif
Then, the C++ code could implement the function like:
typedef std::map<int, void *> map_int_ptr;
int c_map_int_ptr_find (struct c_map_int_ptr *cmap, int key, void **data) {
map_int_ptr &map = *static_cast<map_int_ptr *>(cmap);
map_int_ptr::iterator i = map.find(key);
if (i != map.end()) {
*data = i->second;
return 0;
}
return -1;
}
Thus, there is no need to pass the arguments passed via the C interface through a variable argument adapter. And so, there is no need for the C++ code to tease out the arguments from a variable argument list. The C code calls directly into the C++ code, which knows what to do with the arguments.
I suppose if you are trying to implement some kind of automated C adapter code generator by parsing C++ code, you could think that using variable arguments would provide a regular mechanism to communicate arguments between the generated C code interface and the generated C++ adapter code that would call the original C++ interface. For such a scenario, the code for the above example would look something like this:
// C interface
typedef struct c_map_int_ptr c_map_int_ptr;
typedef struct c_map_int_ptr_iterator c_map_int_ptr_iterator;
//...
c_map_int_ptr_iterator c_map_int_ptr_find (c_map_int_ptr *map, int key) {
c_map_int_ptr_iterator result;
cpp_map_int_ptr_adapter(__func__, map, key, &result);
return result;
}
// C++ code:
struct cpp_adapter {
virtual ~cpp_adapter () {}
virtual void execute (va_list) {}
};
void cpp_map_int_ptr_adapter(const char *func, ...) {
va_list ap;
va_start(ap, func);
cpp_map_int_ptr_adapter_method_lookup(func).execute(ap);
va_end(ap);
}
//...
struct cpp_map_int_ptr_find_adapter : cpp_adapter {
void execute (va_list ap) {
map_int_ptr *map = va_arg(ap, map_int_ptr *);
int key = va_arg(ap, int);
c_map_int_ptr_iterator *c_iter = va_arg(ap, c_map_int_ptr_iterator *);
map_int_ptr::iterator i = map->find(key);
//...transfer result to c_iter
}
};
Where cpp_map_int_ptr_adapter_method_lookup() returns an appropriate cpp_adapter instance based on a table lookup.
Related
The Goal:
decide during runtime which templated function to use and then use it later without needing the type information.
A Partial Solution:
for functions where the parameter itself is not templated we can do:
int (*func_ptr)(void*) = &my_templated_func<type_a,type_b>;
this line of code can be modified for use in an if statement with different types for type_a and type_b thus giving us a templated function whose types are determined during runtime:
int (*func_ptr)(void*) = NULL;
if (/* case 1*/)
func_ptr = &my_templated_func<int, float>;
else
func_ptr = &my_templated_func<float, float>;
The Remaining Problem:
How do I do this when the parameter is a templated pointer?
for example, this is something along the lines of what I would like to do:
int (*func_ptr)(templated_struct<type_a,type_b>*); // This won't work cause I don't know type_a or type_b yet
if (/* case 1 */) {
func_ptr = &my_templated_func<int,float>;
arg = calloc(sizeof(templated_struct<int,float>, 1);
}
else {
func_ptr = &my_templated_func<float,float>;
arg = calloc(sizeof(templated_struct<float,float>, 1);
}
func_ptr(arg);
except I would like type_a, and type_b to be determined during runtime. I see to parts to the problem.
What is the function pointers type?
How do I call this function?
I think I have the answer for (2): simply cast the parameter to void* and the template function should do an implicit cast using the function definition (lease correct me if this won't work as I think it will).
(1) is where I am getting stuck since the function pointer must include the parameter types. This is different from the partial solution because for the function pointer definition we were able to "ignore" the template aspect of the function since all we really need is the address of the function.
Alternatively there might be a much better way to accomplish my goal and if so I am all ears.
Thanks to the answer by #Jeffrey I was able to come up with this short example of what I am trying to accomplish:
template <typename A, typename B>
struct args_st {
A argA;
B argB;
}
template<typename A, typename B>
void f(struct args_st<A,B> *args) {}
template<typename A, typename B>
void g(struct args_st<A,B> *args) {}
int someFunction() {
void *args;
// someType needs to know that an args_st struct is going to be passed
// in but doesn't need to know the type of A or B those are compiled
// into the function and with this code, A and B are guaranteed to match
// between the function and argument.
someType func_ptr;
if (/* some runtime condition */) {
args = calloc(sizeof(struct args_st<int,float>), 1);
f((struct args_st<int,float> *) args); // this works
func_ptr = &g<int,float>; // func_ptr should know that it takes an argument of struct args_st<int,float>
}
else {
args = calloc(sizeof(struct args_st<float,float>), 1);
f((struct args_st<float,float> *) args); // this also works
func_ptr = &g<float,float>; // func_ptr should know that it takes an argument of struct args_st<float,float>
}
/* other code that does stuff with args */
// note that I could do another if statement here to decide which
// version of g to use (like I did for f) I am just trying to figure out
// a way to avoid that because the if statement could have a lot of
// different cases similarly I would like to be able to just write one
// line of code that calls f because that could eliminate many lines of
// (sort of) duplicate code
func_ptr(args);
return 0; // Arbitrary value
}
Can't you use a std::function, and use lambdas to capture everything you need? It doesn't appear that your functions take parameters, so this would work.
ie
std::function<void()> callIt;
if(/*case 1*/)
{
callIt = [](){ myTemplatedFunction<int, int>(); }
}
else
{
callIt = []() {myTemplatedFunction<float, float>(); }
}
callIt();
If I understand correctly, What you want to do boils down to:
template<typename T>
void f(T)
{
}
int somewhere()
{
someType func_ptr;
int arg = 0;
if (/* something known at runtime */)
{
func_ptr = &f<float>;
}
else
{
func_ptr = &f<int>;
}
func_ptr(arg);
}
You cannot do that in C++. C++ is statically typed, the template types are all resolved at compile time. If a construct allowed you to do this, the compiler could not know which templates must be instanciated with which types.
The alternatives are:
inheritance for runtime polymorphism
C-style void* everywhere if you want to deal yourself with the underlying types
Edit:
Reading the edited question:
func_ptr should know that it takes an argument of struct args_st<float,float>
func_ptr should know that it takes an argument of struct args_st<int,float>
Those are incompatible. The way this is done in C++ is by typing func_ptr accordingly to the types it takes. It cannot be both/all/any.
If there existed a type for func_ptr so that it could take arguments of arbitrary types, then you could pass it around between functions and compilation units and your language would suddenly not be statically typed. You'd end up with Python ;-p
Maybe you want something like this:
#include <iostream>
template <typename T>
void foo(const T& t) {
std::cout << "foo";
}
template <typename T>
void bar(const T& t) {
std::cout << "bar";
}
template <typename T>
using f_ptr = void (*)(const T&);
int main() {
f_ptr<int> a = &bar<int>;
f_ptr<double> b = &foo<double>;
a(1);
b(4.2);
}
Functions taking different parameters are of different type, hence you cannot have a f_ptr<int> point to bar<double>. Otherwise, functions you get from instantiating a function template can be stored in function pointers just like other functions, eg you can have a f_ptr<int> holding either &foo<int> or &bar<int>.
Disclaimer: I have already provided an answer that directly addresses the question. In this answer, I would like to side-step the question and render it moot.
As a rule of thumb, the following code structure is an inferior design in most procedural languages (not just C++).
if ( conditionA ) {
// Do task 1A
}
else {
// Do task 1B
}
// Do common tasks
if ( conditionA ) {
// Do task 2A
}
else {
// Do task 2B
}
You seem to have recognized the drawbacks in this design, as you are trying to eliminate the need for a second if-else in someFunction(). However, your solution is not as clean as it could be.
It is usually better (for code readability and maintainability) to move the common tasks to a separate function, rather than trying to do everything in one function. This gives a code structure more like the following, where the common tasks have been moved to the function foo().
if ( conditionA ) {
// Do task 1A
foo( /* arguments might be needed */ );
// Do task 2A
}
else {
// Do task 1B
foo( /* arguments might be needed */ );
// Do task 2B
}
As a demonstration of the utility of this rule of thumb, let's apply it to someFunction(). ... and eliminate the need for dynamic memory allocation ... and a bit of cleanup ... unfortunately, addressing that nasty void* is out-of-scope ... I'll leave it up to the reader to evaluate the end result. The one feature I will point out is that there is no longer a reason to consider storing a "generic templated function pointer", rendering the asked question moot.
// Ideally, the parameter's type would not be `void*`.
// I leave that for a future refinement.
void foo(void * args) {
/* other code that does stuff with args */
}
int someFunction(bool condition) {
if (/* some runtime condition */) {
args_st<int,float> args;
foo(&args);
f(&args); // Next step: pass by reference instead of passing a pointer
}
else {
args_st<float,float> args;
foo(&args);
f(&args); // Next step: pass by reference instead of passing a pointer
}
return 0;
}
Your choice of manual memory management and over-use of the keyword struct suggests you come from a C background and have not yet really converted to C++ programming. As a result, there are many areas for improvement, and you might find that your current approach should be tossed. However, that is a future step. There is a learning process involved, and incremental improvements to your current code is one way to get there.
First, I'd like to get rid of the C-style memory management. Most of the time, using calloc in C++ code is wrong. Let's replace the raw pointer with a smart pointer. A shared_ptr looks like it will help the process along.
// Instead of a raw pointer to void, use a smart pointer to void.
std::shared_ptr<void> args;
// Use C++ memory management, not calloc.
args = std::make_shared<args_st<int,float>>();
// or
args = std::make_shared<args_st<float,float>>();
This is still not great, as it still uses a pointer to void, which is rarely needed in C++ code unless interfacing with a library written in C. It is, though, an improvement. One side effect of using a pointer to void is the need for casts to get back to the original type. This should be avoided. I can address this in your code by defining correctly-typed variables inside the if statement. The args variable will still be used to hold your pointer once the correctly-typed variables go out of scope.
More improvements along this vein can come later.
The key improvement I would make is to use the functional std::function instead of a function pointer. A std::function is a generalization of a function pointer, able to do more albeit with more overhead. The overhead is warranted here in the interest of robust code.
An advantage of std::function is that the parameter to g() does not need to be known by the code that invokes the std::function. The old style of doing this was std::bind, but lambdas provide a more readable approach. Not only do you not have to worry about the type of args when it comes time to call your function, you don't even need to worry about args.
int someFunction() {
// Use a smart pointer so you do not have to worry about releasing the memory.
std::shared_ptr<void> args;
// Use a functional as a more convenient alternative to a function pointer.
// Note the lack of parameters (nothing inside the parentheses).
std::function<void()> func;
if ( /* some runtime condition */ ) {
// Start with a pointer to something other than void.
auto real_args = std::make_shared<args_st<int,float>>();
// An immediate function call:
f(real_args.get());
// Choosing a function to be called later:
// Note that this captures a pointer to the data, not a copy of the data.
// Hence changes to the data will be reflected when this is invoked.
func = [real_args]() { g(real_args.get()); };
// It's only here, as real_args is about to go out of scope, where
// we lose the type information.
args = real_args;
}
else {
// Similar to the above, so I'll reduce the commentary.
auto real_args = std::make_shared<args_st<float,float>>();
func = [real_args]() { g(real_args.get()); };
args = real_args;
}
/* other code that does stuff with args */
/* This code is probably poor C++ style, but that can be addressed later. */
// Invoke the function.
func();
return 0;
}
Your next step probably should be to do some reading on these features so you understand what this code does. Then you should be in a better position to leverage the power of C++.
I have a module which receives ASCII commands and then reacts to them accordingly. I am wondering if it is possible, to have a more robust and typesafe way of calling handler functions.
In the past, I had code like the following, which is also very similar to this answer: Processing ASCII commands via RS232 in embedded c
struct Command commands[] = {
{"command1", command1Handler}
{"command2", command2Handler}
...
};
//gets called when a new string has been received
void parseCmd(const char *input) {
//find the fitting command entry and call function pointer
}
bool command1Handler(const char *input) { }
bool command2Handler(const char *input) { }
I don't like that all handler functions have to do their own parsing. This seems needlessly repetitive and error prone.
It would be cool, if instead we could have it the following way, where all parsing is done in the the parseCmd function:
struct Command commands[] = {
{"command1", command1HandlerSafe}
{"command2", command2HandlerSafe}
...
};
void parseCmd(const char *input) {
//1. find fitting command entry
//2. check that parameter number fits the expected number for the target function
//3. parse parameters and validate the types
//4. call function with parameters in their correct types
}
bool command1HandlerSafe(bool param1, const char *param2) { }
bool command2HandlerSafe(int param1) {}
I think with old C-style varargs it would be possible to do the parsing in a central function, but that would not bring type safety.
Edit:
Meanwhile I came up with the following solution, which I thought somewhat balances the hackiness and modularization:
class ParameterSet{
struct Param{
const char *paramString;
bool isInt();
int toInt();
float toFloat();
..
}
ParameterSet(const char *input);
Param at(size_t index);
size_t length();
char m_buffer[100];
Param m_params[10];
}
bool command1HandlerMoreSafe(const ParameterSet *paramSet);
Building an abstraction layer around this might make things more complex and thereby bug prone. I wouldn't do that unless the amount of commands you are supposed to handle is vast, needs to be maintained, and this is one of the main tasks of your application.
With the pre-requisites to keep type safe and keep parsing separate from algorithms, you could build something similar to the following C-like pseudo code:
typedef enum
{
INT,
STR
} type_t; // for marking which type that is supported by the command
typedef struct
{
type_t type;
const char* text; // what kind of text that is expected in case of strings
} arg_t;
typedef struct
{
const char* name; // the name of the command
arg_t* args; // list of allowed arguments
size_t args_n; // size of that list
void (*callback)(void); // placeholder for callback functions of different types
} command_t;
You can then make callback handler functions that aren't concerned about parsing, but only about their dedicated task:
void cmd_branch (const char* str);
void cmd_kill (int n);
The array of commands might look something like this:
const command_t commands[] =
{
{ // BRANCH [FAST][SLOW]
.name="BRANCH",
.args=(entry_t[]){ {STR,"FAST"}, {STR,"SLOW"} },
.args_n=2,
.callback= (void(*)(void)) cmd_branch,
},
{ // KILL [7][9]
.name="KILL",
.args=(entry_t[]){ {INT, NULL} },
.args_n=1,
.callback= (void(*)(void)) cmd_kill,
}
};
The parse function will then do:
Find which command that was received by searching the above list (bsearch if large list).
Check what type of arguments the received command supports
Parse arguments accordingly
Call the relevant function with arguments of the appropriate type
Since this example just used some dummy type function pointer (void(*)(void)), you'll have to cast to the correct type. Can be done by for example C11 _Generic:
call(commands[i], int_val);
which expands to:
#define call(command, arg) _Generic((arg), \
int: (void(*)(int)) command.callback, \
const char*: (void(*)(const char*)) command.callback )(arg)
One way to keep the command handling interfaces the same is to fall back on the venerable argv / argc interface that main() receives. Assuming the received commands have some notion of words (perhaps whitespace separated), it could go like this:
Receive the input string.
Parse the input into words where the first word is the name of the command and the remaining words are its arguments.
As the parsing proceeds, place a pointer to the string that contains each word in an array and keep count of the number of elements in the array.
Using the first word, look up a command function pointer. You can use something like bsearch() if the commands are all known at compile time. Perhaps a hash table might also be appropriate. However you implement the mapping, the result is a pointer to a function that takes an array of pointers to the arguments and a count of the number of elements in the pointer array.
Invoke the command function via its pointer and pass the array of parsed words and the count, just like main() is invoked by startup code.
From there, each command function can deal with what its arguments specifically mean, converting strings representations to internal forms as necessary.
I need to register functions like the following in a list of functions with arguments.
void func1( int a , char* b ) {}
void func2( vec3f a , std::vector<float> b , double c) {}
...
And call them back when I receive data over network with proper arguments. I imagined va_list would solve, but it doesnt work :
void func1(int a, char* b)
{
printf("%d %s",a,b);
}
void prepare(...)
{
va_list argList;
int args = 2;
va_start(argList, args);
((void (*)(va_list))func1)(argList);
va_end(argList);
}
int main(int argc, char **argv)
{
prepare(1, "huhu");
return 0;
}
What is the most elegant way to solve this ?
I know std::bind / std::function has similar abilities, but the internal data is hidden deep in std I assume. I just need a few basic data types, doesnt have to be for arbitrary types. If preprocessor tricks with ##VA_ARGS or using templates would solve, I am also OK with that. Priority is that it is most simple to use.
Edit1 : I found that assembly can solve ( How do I pass arguments to C++ functions when I call them from inline assembly ) - but I would prefer a more platform independent solution.
If your goal is to create your own, small and ad-hoc "rpc" solution, possibly one of the major drivers for making decisions should be: 1. Minimal amount of code 2. Easy as possible.
Keeping that in mind, it is paying off to ponder, what the difference is between the following 2 scenarios:
"Real" RPC: The handlers shall be as you wrote with rpc-method-specific signature.
"Message passing": The handlers receive messages of either "end point-determined type" or simply of a unified message type.
Now, what has to be done to get a solution of type 1?
Incoming byte streams/network packets need to get parsed to some sort of message with regards to some chosen protocol. Then, using some meta-info (contract), according to { serviceContract, serviceMethod }, a specific set of data items needs to be confirmed in the packet and if present, the respective, registered handler function needs to be called. Somewhere within that infrastructure you typically have a (likely code generated) function which does something like that:
void CallHandlerForRpcXYCallFoo( const RpcMessage*message )
{
uint32_t arg0 = message->getAsUint32(0);
// ...
float argN = message->getAsFloat(N);
Foo( arg0, arg1, ... argN );
}
All that can, of course also be packed into classes and virtual methods with the classes being generated from the service contract meta data. Maybe, there is also a way by means of some excessive template voodoo to avoid generating code and having a more generic meta-implementation. But, all that is work, real work. Way too much work to do it just for fun. Instead of doing that, it would be easier to use one of the dozens technologies which do that already.
Worth noting so far is: Somewhere within that piece of art, there is likely a (code generated) function which looks like the one given above.
Now, what has to be done to get a solution of type 2?
Less than for case 1. Why? Because you simply stop your implementation at calling those handler methods, which all take the RpcMessage as their single argument. As such, you can get away without generating the "make-it-look-like-a-function-call" layer above those methods.
Not only is it less work, it is also more robust in the presence of some scenarios where the contract changes. If one more data item is being added to the "rpc solution", the signature of the "rpc function" MUST change. Code re-generated, application code adapted. And that, whether or not the application needs that new data item. On the other hand, in approach 2, there are no breaking changes in the code. Of course, depending on your choices and the kind of changes in the contract, it still would break.
So, the most elegant solution is: Don't do RPC, do message passing. Preferably in a REST-ful way.
Also, if you prefer a "unified" rpc message over a number of rpc-contract specific message types, you remove another reason for code bloat.
Just in case, what I say seems a bit too abstract, here some mock-up dummy code, sketching solution 2:
#include <cstdio>
#include <cstdint>
#include <map>
#include <vector>
#include <deque>
#include <functional>
// "rpc" infrastructure (could be an API for a dll or a lib or so:
// Just one way to do it. Somehow, your various data types need
// to be handled/represented.
class RpcVariant
{
public:
enum class VariantType
{
RVT_EMPTY,
RVT_UINT,
RVT_SINT,
RVT_FLOAT32,
RVT_BYTES
};
private:
VariantType m_type;
uint64_t m_uintValue;
int64_t m_intValue;
float m_floatValue;
std::vector<uint8_t> m_bytesValue;
explicit RpcVariant(VariantType type)
: m_type(type)
{
}
public:
static RpcVariant MakeEmpty()
{
RpcVariant result(VariantType::RVT_EMPTY);
return result;
}
static RpcVariant MakeUint(uint64_t value)
{
RpcVariant result(VariantType::RVT_UINT);
result.m_uintValue = value;
return result;
}
// ... More make-functions
uint64_t AsUint() const
{
// TODO: check if correct type...
return m_uintValue;
}
// ... More AsXXX() functions
// ... Some ToWire()/FromWire() functions...
};
typedef std::map<uint32_t, RpcVariant> RpcMessage_t;
typedef std::function<void(const RpcMessage_t *)> RpcHandler_t;
void RpcInit();
void RpcUninit();
// application writes handlers and registers them with the infrastructure.
// rpc_context_id can be anything opportune - chose uint32_t, here.
// could as well be a string or a pair of values (service,method) or whatever.
void RpcRegisterHandler(uint32_t rpc_context_id, RpcHandler_t handler);
// Then according to taste/style preferences some receive function which uses the registered information and dispatches to the handlers...
void RpcReceive();
void RpcBeginReceive();
void RpcEndReceive();
// maybe some sending, too...
void RpcSend(uint32_t rpc_context_id, const RpcMessage_t * message);
int main(int argc, const char * argv[])
{
RpcInit();
RpcRegisterHandler(42, [](const RpcMessage_t *message) { puts("message type 42 received."); });
RpcRegisterHandler(43, [](const RpcMessage_t *message) { puts("message type 43 received."); });
while (true)
{
RpcReceive();
}
RpcUninit();
return 0;
}
And if RpcMessage then is traded, while packed in a std::shared_ptr, you can even have multiple handlers or do some forwarding (to other threads) of the same message instance. This is one particularly annoying thing, which needs yet another "serializing" in the rpc approach. Here, you simply forward the message.
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?
Is it possible to store pointers to various heterogenous functions like:
In the header:
int functionA (int param1);
void functionB (void);
Basically this would the part I don't know how to write:
typedef ??boost::function<void(void)>?? functionPointer;
And afterwards:
map<char*,functionPointer> _myMap;
In the .cpp
void CreateFunctionMap()
{
_myMap["functionA"] = &functionA;
_myMap["functionB"] = &functionB;
...
}
And then reuse it like:
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
functionPointer mfp;
mfp = map[argv[0]];
answer = *mfp(param);
}
else{
*map[argv[0]];
}
}
etc.
Thanks
--EDIT--
Just to give more info:
The reason for this question is that I am implementing a drop-down "quake-style" console for an already existing application. This way I can provide runtime command line user input to access various already coded functions of various types i.e.:
/exec <functionName> <param1> <param2> ...
If you want to have "pointer to something, but I'm not going to define what, and it could be a variety of things anyway" you can use void *.
But you really shouldn't.
void * is purely a pointer. In order to do anything with it, you have to cast it to a more meaningful pointer, but at that point, you've lost all type safety. What's to stop someone from using the wrong function signature? Or using a pointer to a struct?
EDIT
To give you a more useful answer, there's no need to put this all into a single map. It's ok to use multiple maps. I.e.
typedef boost::function<void(void)> voidFunctionPointer;
typedef boost::function<int(int)> intFunctionPointer;
map<std::string, voidFunctionPointer> _myVoidMap;
map<std::string, intFunctionPointer > _myIntMap;
void CreateFunctionMap()
{
_myVoidMap["functionA"] = &functionA;
_myIntMap["functionB"] = &functionB;
...
}
void execute(int argc, char* argv[])
{
if(argc>1){
int param = atoi(argv[1]);
int answer;
// todo: check that argv[0] is actually in the map
intFunctionPointer mfp = _myIntMap[argv[0]];
answer = mfp(param);
}
else{
// todo: check that argv[0] is actually in the map
voidFunctionPointer mfp = _myVoidMap[argv[0]];
mfp();
}
}
You can use
boost::variant<
boost::function<void(void)>,
boost::function<void(int)> >
Why not just add functions of type int (*func)(int argc, char* argv[])? You could easily remove first arg from execute's params and call the relevant one.
Can you not use the command pattern to encapsulate the function calls. So you can store the functions in functors and call them after wards. For functor implementation you can have a look at Modern C++ Design by Andrei Alexandrescu.
Each of your functions has a different type, so you need some kind of type erasure. You could use the most generic of them: Boost.Any. You can have a map of boost::any, but you need to know the type of the function in order to get it back and call it.
Alternatively, if you know your arguments ahead of time you can bind them with the function call and have all functions in the map be nullary functions: function< void() >. Even if you don't, you may be able to get away with it by binding the argument to references, and then at call time fill the referred variables with the appropiate arguments.