I’m trying to reimplement in a backward-compatible way the RobotC API from C (although some details such as automatical inclusion of stdbool, optional parameters, references, I/O through “array”/subscript notation value/assignment, etc. would better fit C++ and some issues may be easier to solve in C++…). This one includes void startTask(void TaskID, short nTaskPriority) and void stopTask(void TaskID) to enable multithreading.
TaskID is meant to directly be the name of the function to run in a new thread. So no thread number variable there, only the global-scope function name. I first tried to implement something near this using macro identifier concatenation and external variables, but I can’t define a global variable from inside a function (using extern would result in a declaration rather than a definition, and a definition in a function is by default in local scope), so I end up with something that works only in the same scope (or stopping from an inner scope would work, but not the other way).
How could I do something alike? for example how to define (for example using some complex macro trick, a gcc extension (though I’d prefer to stay standard if possible, but wouldn’t bother too much if a such feature required gcc), or whatever?) a global, preferably multi-file, namespace-unique, made-up variable, for storing the pthread id?
#include <stdlib.h>
#include <pthread.h>
#include <stdarg.h>
#include <sched.h>
#include "misc.c"
const short kHighPriority = 255;
const short kLowPriority = 0;
const short kDefaultTaskPriority = 7;
/* void startTask(void TaskID,
short nTaskPriority = kDefaultTaskPriority) */
pthread_t
startTask (task (*TaskID)(void*), short nTaskPriority)
{
pthread_attr_t attr;
pthread_t thread;
struct sched_param param;
const int policy = sched_getscheduler(0),
sched_high_prio = sched_get_priority_max(policy), // 19,
sched_low_prio = sched_get_priority_min(policy), // -20,
sched_range_prio = sched_high_prio - sched_low_prio;
pthread_attr_init (&attr);
pthread_attr_getinheritsched(&attr, PTHREAD_INHERIT_SCHED);
pthread_attr_getschedparam (&attr, ¶m);
param.sched_priority = -(((nTaskPriority
- kLowPriority) * sched_range_prio
/ kHighPriority) + sched_low_prio);
pthread_attr_setschedparam (&attr, ¶m);
pthread_create (&thread, &attr, (void*) TaskID, NULL);
return thread;
}
void
stopTask (pthread_t thread)
{
pthread_cancel(thread);
}
void
stopAllTasks ()
{
exit(0);
}
#define startTask(task, priority) \
static pthread_t task##_thread = startTask(task, priority)
#define stopTask(task) \
stopTask(task##_thread)
I’d prefer, ideally, to solve this problem without external (that is, non-standard) libraries, at compile time, with C instead of C++, standard (C11 doesn’t disturb me) if possible, in this order (!gcc-specific || ! cxx || compile-time || stdc).
That is, except if something else is found, I’m okay with C++, even more with GNU extensions and totally okay with C/C++11 to solve this problem at compile-time instead of runtime, for instance (though my reimplementation seems mostly standard to me, global-scope multithreading requiring GNU doesn’t seems too much).
I would use a dictionary. A dictionary associates keys with values. The key is this case would by the task name, converted to a string. And the value would be the thread ID from pthread_create.
The dictionary itself could be implemented any way you like: hash table, binary tree, linked list, or even an array. The dictionary interface consists of three functions: Add(), Find(), and Remove().
To use the dictionary, the startTask and stopTask macros convert the function name to a string using the # operator. The string is then passed to the StartTask and StopTask functions and used as the key in the dictionary.
Here's some sample code that demonstrates the concepts:
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#define startTask(task, priority) startTask(#task, task, priority)
#define stopTask(task) stopTask(#task)
void dictionaryAdd(char *key, pthread_t threadID)
{
printf("Adding key: %s\n", key);
// add the key with its associated threadID to the dictionary
}
bool dictionaryFind(char *key, pthread_t *threadID)
{
printf("Finding key: %s\n", key);
// find the key in the dictionary and get the associated threadID
*threadID = 0;
return true;
}
void dictionaryRemove(char *key)
{
// remove the key and associated value from the dictionary
printf("Removing key: %s\n", key);
}
void startTask(char *name, ...)
{
pthread_t threadID = 0;
pthread_create(&threadID, ...);
dictionaryAdd(name, threadID);
}
void stopTask(char *name)
{
pthread_t threadID;
if (dictionaryFind(name, &threadID))
{
pthread_cancel(threadID);
dictionaryRemove(name);
}
}
void *foo(void *arg)
{
return NULL;
}
int main(void)
{
startTask(foo, 10);
stopTask(foo);
}
The output from the code:
Adding key: foo
Finding key: foo
Removing key: foo
Related
could you please help in following.
I have callback function definition in the 3rd lib header:
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*SOCK_CLBK)(int, short, unsigned char*, int, ...);
#ifdef __cplusplus
}
#endif
And I define my callback in the following way:
header file:
template<typename T>
int ReadTCP(int socket, short code, unsigned char* msg, int received, T a);
cpp file:
template<>
int ReadTCP(int socket, short code, unsigned char* msg, int received, int a)
{
return 0;
}
and register my callback in the code:
server->registerCallback(port, (SOCK_CLBK)(ReadTCP<int>),maxTCPsize);
This works fine, and the callback is triggered when needed.
The problem is, the "int a" contains random values every time.
how to register a callback and pass my own specific value for example 100000, that will occur in the callback in "a"?
Something like
server->registerCallback(port, (SOCK_CLBK)(&std::bind(ReadTCP<int>,_1,_2,_3,_4, 100000),maxTCPsize);
but this does not work (triggers runtime exception).
What I am doing wrong?
lib header:
#include "CSocket.h"
#ifndef WIN32
#include <pthread.h>
#else
#include <windows.h>
#include <WinSock.h>
#endif
#define CPP_TCP_MAX_CLIENTS 17
#define CPP_TCP_MAX_SIZE 1500 //In accordance with MTU definitoins
class DLLCPP_API CSERVER {
public:
/**
* default constructor
*/
CSERVER ();
/**
* default destructor
*/
virtual ~CSERVER ();
/**! \fn int Create(unsigned int uiPort, bool bClbk);
* \brief creates singleton socket listener
* creates singleton socket listener, which is invoked within dedicated thread
* if bClbk is true, otherwise within the main thread.
* \param uiPort socket listener port
* \param fnClbk call-back function address. if not NULL then callback mode of operation. otherwise normal.
* \return 0 on success, error id otherwise.
*/
int registerCallback(unsigned int uiPort, SOCK_CLBK fnClbk=NULL, int iMsgMaxSize=512)throw (CMException);
….
…
Send()…
….
...
protected:
#ifndef WIN32
friend void* _fnTCPClbkThread(void *); //call-back argument for pthread_create within RunClbkThread.
#else
friend DWORD WINAPI _fnTCPClbkThread( LPVOID lpParam );
#endif
/**! \fn int IsPending(int iSock, bool& bFail)
* \brief check pending connection on a non blocking socket
* actuall checks for errors and whether or not connection is ready for write operation.
* \param iSock client socket connection to check.
* \return: OK (0) if iSock ready for write operation or ERROR otherwise (still pending for instance)
*/
int IsPending(int iSock)throw (CMException);
int RunClbkThread();
int CreateClbk()throw (CMException);
void ClbkThread();
private:
typedef void (CSERVER::*PCLBKTHREAD)(void *);
PCLBKTHREAD _pThreadClbk;
int _iServerSock;
int _iSock;
SOCK_CLBK _fnClbk;
unsigned int _uiPort;
int _iAddrLen;
bool _bClbkThreadAlive;
int _iClientConnectionsArr[CPP_TCP_MAX_CLIENTS];
int _iMsgMaxSize;
struct sockaddr_in _saddConnect ;
#ifdef WIN32
WSADATA m_wsaData;
HANDLE _thread;
#else
pthread_t _thread;
#endif
};
Look at function registerCallback
From which I can deduct that the class does not store any user data to be passed later as a callback parameter... Why do they have variadic template then - no idea.
First, your code with ReadTCP function template is incorrect. SOCK_CLBK is a type of a function pointer that has an ellipsis at the end of its argument list, which is different from int (or any other type) that ReadTCP<int> has. The compiler does not fail to compile because you explicitly convert the pointer to ReadTCP<int> to SOCK_CLBK, but the call fails at runtime (you either receive a random value in the int a argument or crash).
Your second piece of code with std::bind is also wrong because std::bind returns a function object, not a pointer to function. The function object has operator(), so it can be called like a function, but it cannot be converted to a function pointer (for one, because the object also contains data, like the arguments you bound).
You must define a function that accepts a variable number of arguments (i.e. has an ellipsis at the end of its argument list) and pass that function as the callback. In that function, you can process the passed arguments and possibly invoke other specialized functions in your code, like ReadTCP.
int ReadTCPCallback(int socket, short code, unsigned char* msg, int received, ...)
{
std::va_list args;
va_start(args, received);
// Use variable arguments here, using va_arg. Consult with the API
// documentation to know what arguments are expected here. For the sake
// of this example, let's assume an int argument is passed.
int n = va_arg(args, int);
int res = ReadTCP(socket, code, msg, received, n);
// Always call va_end before returning once you're done with va_list
va_end(args);
return res;
}
If you want to use function objects with this API then you will have to find a way to pass a pointer to data through the third party library to the callback. That data will contain the bound parameters and other state pertinent to the call. Refer to the documentation of that third party library as to how to pass user's data to the callback.
If the API does not support passing user's data (which would make it a rather poorly designed API), you could associate the data with some handle returned by the API that corresponds to your state. For example, you could maintain a global std::map to map the socket file descriptor (int) to a pointer to your data related to that socket or connection.
I am trying to print IT SUCCESS\nET SUCCESS\n using following code but it's failing in compilation with error error: ‘printds’ was not declared in this scope which I know is because it's taking macro input as ds literal. Does anyone know how to do this? The use case is that there are several printXX() functions which should be called based on value passed in macro.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", es = "ET";
FOO(ds); FOO(es);
return 0;
}
You can change
FOO(ds); FOO(es);
to
FOO(IT); FOO(ET);
Because macro substitutions happen before your code is compiled.
But you can define a function called FOO like
#include <stdio.h>
#include <iostream>
using namespace std;
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
void FOO(const string str)
{
if(str=="IT")
printIT();
else
printET();
}
int main()
{
const char* ds = "IT",*es="ET";
FOO(ds);FOO(es);
return 0;
}
it's taking macro input as ds literal.
Yes, that's to be expected. Preprocessor macros are expanded at compile time. The arguments to function-like macros are the literal source-code tokens that appear between the parentheses in the macro invocation. These have no additional meaning to the preprocessor.
Does anyone know how to do this? The use case is that there are several printXX() functions which should be called based on value passed in macro.
Again, macros are expanded, to source code (approximately), at compile time. The process does not and cannot take into account C++ runtime semantics such as converting variables' identifiers into corresponding values.
If runtime dynamic function dispatch based on variables' values is what you're after then you need an altogether different mechanism. You could use ordinary conditional statements to select between different function calls, for example. If you wanted to be even more dynamic then you could consider preparing a lookup table of function pointers, and using that to select and call appropriate functions.
In comments, you added
I've several methods queryServers, queryNodes, queryTargets which I want to call using above trick.
You may be able to accomplish something similar to what you ask via templates or overloaded functions. These mechanisms, too, operate at compile time, so they have no access to runtime information such as variables' values, but they do know about and rely upon C++ data types.
Alternatively, perhaps you're looking for the Strategy pattern.
The first thing you need to know is that the Macros are preprocessor directives which are a fragment of code with a given name. if you use macro name in your program it will replace that code fragment into that place you use the macro name at compile time first stage called Pre-processing stage.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", es = "ET";
FOO(ds); FOO(es);
return 0;
}
In your code, you try to input ds and es variables into FOO function like macro. But ds and es variables declared in program stack only when you run the program. At the compile-time, it just treats them as only texts. Therefore macro function input it takes as text ds and es and replaced with val. That's why you got the compile time error. The following code fragment I have changed is working as you expected.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", *es = "ET";
FOO(IT); FOO(ET);
return 0;
}
If you are interested you can find more about Macros in the following resources.
GCC online documentation and Article about Macros . Also, you can view the preprocessed code using g++ -E (your cpp file name). Thanks.
Possible solution without MACRO:
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
void foo(std::string_view s)
{
static const std::map<std::string_view, void(*)()> funcs{
{"IT", &printIT},
{"ET", &printET}
};
auto it = funcs.find(s);
if (it != funcs.end()) {
(*it->second)();
}
}
int main() {
const char* ds = "IT";
const char* es = "ET";
foo(ds); foo(es);
}
Demo
This is my first time posting my own question, so sorry if I break etiquette or something in some way. Most of the software in this program I'm working on wasn't coded by me. I'm wanting to create a thread using one of their functions.The function I want to implement in the thread looks like this. If possible I would like to be able to continue using pthreads:
void * bpsk_continuous(
uhd::usrp::multi_usrp::sptr usrp,
const std::string &cpu_format,
const std::string &wire_format,
const std::string &file,
size_t samps_per_buff,
unsigned long long num_requested_samples,
double time_requested = 0.0,
bool bw_summary = false,
bool stats = false,
bool null = false,
bool enable_size_map = false,
bool continue_on_bad_packet = false
){//operations of function}
Later they use syntax very unfamiliar to me that I'm assuming defines the arguments in some way. My first question would be what is the following code doing.
#define bpsk_continuous_args(format) \
(usrp, format, wirefmt, file, spb, total_num_samps, total_time, bw_summary, stats, null, enable_size_map, continue_on_bad_packet)
//if (type == "float") recv_to_file<std::complex<float> >recv_to_file_args("fc32");
My second question would be how can I create a thread that runs the bpsk_continuous argument given the syntax above. I tried the following but no dice:
pthread_t t1;
pthread_create(&t1, NULL, bpsk_continuous,bpsk_continuous_args("fc32"));
You should create auxiliary struct, and the start routine, lets say:
struct bpsh_args {
uhd::usrp::multi_usrp::sptr usrp;
std::string cpu_format;
std::string wire_format;
std::string file;
size_t samps_per_buff;
unsigned long long num_requested_samples;
double time_requested;
bool bw_summary;
bool stats;
bool null;
bool enable_size_map;
bool continue_on_bad_packet;
};
In the start routine you should cast it's only argument back to bpsh_args:
void* start_routine(void* _args) {
bpsh_args* args = static_cast<bpsh_args*>(_args);
bpsk_continuous(args->usrp, args->cpu_format, ...);
}
Then fill bpsh_args with appropriate data and then pass the pointer to it as last argument of pthread_create, and start_routine as one before last.
bpsh_args _bpsh_args;
_bpsh_args.usrp = ....;
_bpsh_args.cpu_format = "fc32";
...
pthread_create(&t1, NULL, start_routine, &_bpsh_args);
Consult man or http://man7.org/linux/man-pages/man3/pthread_create.3.html for details.
Be aware of the fact that after a new thread is started the struct with arguments is shared between two threads and the _args will be invalid if the variable _bpsh_args goes out of scope. Maybe you should better allocate it on heap, or add some synchronisation primitives to ensure that _bpsh_args is alive as long as you use it in descendant thread.
To answer your first question, what the #define does, it is a so-called macro. Macros just perform text replacement. Just do a little research and you will find out more about them, in particular that they are generally considered an evil feature of C++.
Then, if you need to rule out using a portable approach like std::thread (or even Boost's variant thereof), try this approach:
void* thread_function(void* arg)
{
assert(arg);
std::string const& format = *static_cast<std::string*>(arg);
return bpsk_continuous bpsk_continuous_args(format);
}
somewhere()
{
std::string format = ...;
pthread_create(.., &thread_function, &format, ..);
}
Note that this library is from what I can tell shoddy C++. The use of lower-case macros. Using them to work around its own overly long parameter lists. The seeming lack of understanding for namespaces. These all seems like a poor design choices to me and I wouldn't be surprised to find more of them.
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.
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.