I'm writing a C backend for a C++ library and I want the C code to be able to iterate over the individual items of a forward iterator. In C++ the code which iterates over the items looks like this:
auto rng = wks.range(XLCellReference("A1"), XLCellReference("Q1"));
for (auto& cell : rng) {
// do something with "cell"
}
Now I want to export this code so that it is accessible from C. I'd like to be able to iterate over the items from C using a set of functions like this:
void *startiteration(void *cpp_obj);
void *getnextitem(void *cpp_obj, void *iter);
void finishiteration(void *cpp_obj, void *iter);
I'd imagine startiteration() to return an iterator pointer to the C code which would then be passed along with the C++ object pointer for all successive calls to getnextitem() and finishiteration().
But the problem here is that I can easily pass pointers of objects created in C++ using new between C and C++ code but I don't see how I could do the same with iterators since the iterators are returned by a class method and I don't think there's any way to turn the iterator into a pointer that I could pass to C code which would then pass it back to C++ during the iteration. Also, I don't know how I would "free" such an iterator.
Does anybody have some tips how I can iterate over a C++ forward iterator from C code? How should this be implemented?
EDIT
Implementation based on Silvio's suggestions:
struct myiter
{
XLCellIterator begin;
XLCellIterator end;
};
void *xlsx_startiteration(void *handle, int idx)
{
XLDocument *doc = (XLDocument *) handle;
XLWorkbook wb = doc->workbook();
auto wks = wb.worksheet(wb.sheetNames()[idx-1]);
XLCellRange cr = wks.range(XLCellReference("A1"), XLCellReference("Q1"));
myiter *it = new myiter();
it->begin = std::begin(static_cast<XLCellRange*>(cr));
it->end = std::end(static_cast<XLCellRange*>(cr));
return it;
}
auto rng = wks.range(XLCellReference("A1"), XLCellReference("Q1"));
for (auto& cell : rng) {
// do something with "cell"
}
I like doing 1:1 relationship between C++ and C. The following code outputs 3 lines var=1 var=2 var=3.
By wrapping the objects inside structures, the C side only forward declarations of structures and pointers. The C++ side sees all the rest. Additionally, C side will get a warning when passing invalid pointer to the wrong function.
#include <cstdio>
#include <vector>
typedef int do_not_know_what_is_the_type;
typedef std::vector<do_not_know_what_is_the_type> XLCellRange;
typedef XLCellRange::iterator XLCellIterator;
// header file
// C side
#ifdef __cplusplus
extern "C" {
#endif
struct wks_range_it_s;
void wks_range_it_inc(struct wks_range_it_s *);
bool wks_range_it_ne(struct wks_range_it_s *, struct wks_range_it_s *);
do_not_know_what_is_the_type wks_range_it_deref(struct wks_range_it_s *);
void wks_range_it_destruct(struct wks_range_it_s *);
struct wks_range_s;
struct wks_range_s *wks_range_construct();
void wks_range_destruct(struct wks_range_s *);
struct wks_range_it_s *wks_range_begin(struct wks_range_s *);
struct wks_range_it_s *wks_range_end(struct wks_range_s *);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
// C++ side
struct wks_range_s {
XLCellRange rng;
};
struct wks_range_it_s {
XLCellIterator it;
};
extern "C"
void wks_range_it_inc(struct wks_range_it_s *t) {
++t->it;
}
extern "C"
bool wks_range_it_ne(struct wks_range_it_s *a, struct wks_range_it_s *b) {
return a->it != b->it;
}
extern "C"
do_not_know_what_is_the_type wks_range_it_deref(struct wks_range_it_s *t) {
return *t->it;
}
extern "C"
void wks_range_it_destruct(struct wks_range_it_s *t) {
delete t;
}
extern "C"
struct wks_range_s *wks_range_construct() {
// return new struct wks_range_s(wks.range(XLCellReference("A1"), XLCellReference("Q1")));
return new wks_range_s{{1,2,3}};
}
extern "C"
void wks_range_destruct(struct wks_range_s *t) {
delete t;
}
extern "C"
struct wks_range_it_s *wks_range_begin(struct wks_range_s *t) {
return new wks_range_it_s{t->rng.begin()};
}
extern "C"
struct wks_range_it_s *wks_range_end(struct wks_range_s *t) {
return new wks_range_it_s{t->rng.end()};
}
#endif
int main() {
// C code example
struct wks_range_s *rng = wks_range_construct();
// Almost 1:1 relationship with C++ range loop.
for(struct wks_range_it_s *begin = wks_range_begin(rng),
*end = wks_range_end(rng);
wks_range_it_ne(begin, end) ? 1 : (
// Yes, I'm sneaky.
wks_range_it_destruct(begin),
wks_range_it_destruct(end),
0);
wks_range_it_inc(begin)
) {
do_not_know_what_is_the_type var = wks_range_it_deref(begin);
// do something with var here?
printf("var=%d\n", var);
}
wks_range_destruct(rng);
}
Forward iterators in C++ are regular, which means they can be copied. In fact, in our case, we would only need to move them. Specifically, assuming the type of the iterator in question is I, then startiteration could do something like this.
struct Range {
I begin;
I end;
};
void* startiteration(void* cpp_obj) {
Range* my_range = new Range();
my_range->begin = std::begin(*static_cast<MyCppType*>(cpp_object));
my_range->end = std::end(*static_cast<MyCppType*>(cpp_object));
return my_range;
}
Just because the forward iterator is originally returned by value doesn't prohibit us from putting it into a pointer, either directly or indirectly. In our case, we grab both the beginning and the end and store them in a (heap-allocated) structure. Then finishiteration, of course, would be responsible for deleteing the constructed range object.
Related
I am currently developing a library in C++ (Mainly because dependent libraries have C++ interfaces). I created a proof-of-concept implementation with C++ interfaces for quick development. The library has to mandatorily provide C interface for it. The C++ interface is good to have but can be modified/removed if it gets in the way of the C interface.
The C++ API right now looks something like this:
typedef struct {
// only basic C data types like int,float.
int a;
float b;
} Object;
typedef struct {
std::vector<Object> objects;
} GroupOfObjects;
typedef struct {
std::vector<GroupOfObjects> groups;
} Result;
typedef struct {
// some basic C data types
int init1;
int init2;
float init3;
// some C++ types which I can possibly replace with something compatible with C
std::string init4;
std::vector<std::string> init5;
} MyClassInitParams;
struct IMyClass {
public:
virtual bool initialize(MyClassInitParams ¶ms) = 0;
virtual bool getResult(Result &result) = 0;
//Other public methods, constructor, virtual destructor
}
// Actual implementation of the above interface
class MyClass : IMyClass {
}
IMyClass *createMyClassInstance();
I have come up with this C interface till now:
extern "C" {
typedef struct MyClass *MyClassHandle;
// A C version of the above MyClassInitParams
typedef struct{
} MyClassInitParams_C;
typedef struct {
Object * objects;
int numObjects;
} GroupOfObjects_C;
// A C version of the above Result structure
typedef struct{
GroupOfObjects_C *groups;
int numGroups;
}Result_C;
MyClassHandle MyClass_Create();
MyClass_Destroy(MyClassHandle handle);
int MyClass_Initialize(MyClassHandle handle, MyClassInitParams_C *params);
int MyClass_GetResult(MyClassHandle handle , Result_C *result);
void MyClass_FreeResult(Result_C *result);
} // end of extern "C"
Implementation of the C interface:
MyClassHandle MyClass_Create()
{
return createMyClassInstance();
}
MyClass_Destroy(MyClassHandle handle)
{
delete handle;
}
int MyClass_Initialize(MyClassHandle handle, MyClassInitParams_C *params)
{
MyClassInitParam params_cpp;
// fill params_cpp using the params structure
return handle->initialize (params_cpp);
}
int MyClass_GetResult(MyClassHandle handle , Result_C *result)
{
Result result_cpp;
bool ret = handle->getResult(result_cpp);
if (!ret)
return 0;
// Fill the C structure using the cpp structure
result->numGroups = result_cpp.groups.size();
result->groups = new GroupOfObjects_C[result->numGroups];
for (int i = 0; i < result->numGroups; i++) {
result->groups[i].numObjects = result_cpp.groups[i].objects.size();
result->groups[i].objects = new Object[result->groups[i].numObjects];
for (int j = 0; j < result->groups[i].numObjects; j++) {
result->groups[i].objects[j] = result_cpp.groups[i].objects[j];
}
}
return 1;
}
void MyClass_FreeResult(Result_C *result) {
// free all the arrays allocated in the above function
}
I have a few questions regarding this:
The GetResult method has a overhead of copying the objects from C++ vectors to the C arrays. Is there a more elegant and efficient way to handle this?
I will have to maintain the structures for both C and C++. Should I just use the C versions of the MyClassInitParams and Result structures in C++ interface? This will also help with (1).
If I use the solution in (2), does it make sense to even have the C++ interface? Or are there any advantages of keeping both the C and C++ interfaces in this case?
I'd suggest to return Result* from C MyClass_GetResult method, like int MyClass_GetResult(MyClassHandle handle, Result_C **result) or Result_C* MyClass_GetResult(MyClassHandle handle). Then, add accessors for groups and objects.
It's up to you to decide, but I'd rather to use one or the other, but not both.
First of all, I'd suggest to decide what language and its features (C or C++) you're going to use in order to implement your business logic. Next, another language becomes nothing more than a wrapper over logic implemented in another language. Again, if you use functions for accessing actual underlying data you'll get rid of copying this data, as you did in MyClass_GetResult method.
Here's an example
struct Object {
int a;
float b;
};
struct GroupOfObjects;
struct Result;
struct MyClass;
#ifdef __cplusplus
#include <vector>
struct GroupOfObjects {
std::vector<Object> objects;
};
struct Result {
std::vector<GroupOfObjects> groups;
};
struct MyClass {
private:
public:
Result getResult() { /*...*/ }
MyClass(int init1, int init2, float init3, const std::string& init4, const std::vector<std::string>& init5);
}
#endif
#ifdef __cplusplus
extern "C" {
#endif __cplusplus
struct Object* GroupOfObjects_GetObject(struct GroupOfObjects* g, size_t i)
/* { return &g.objects[i]; } */ // commented sections must be in cpp file, not in this header
size_t GroupOfObjects_GetCount(struct GroupOfObjects* g)
/* { return g.objects.size(); } */
struct GroupOfObjects* Result_GetGroup(struct Result* r, size_t i)
/* { return &r.groups[i]; } */
size_t Result_GetGroupCount(struct Result* r)
/* { return g.groups.size(); } */
MyClass *CreateMyClassInstance(int init1, int init2, float init3, const char* init4, const char** init5)
/* {
try {
std::vector<std::string> init5_v;
while (init5 != nullptr)
init5_v.push_back(std::string(*init5++));
return new MyClass(init1, init2, init3, std::string(init4), init5_v);
}
catch (...) {
return nullptr;
}
} */
void FreeMyClassInstance(struct MyClass* mc)
/* { delete mc; } */
Result* MyClass_GetResult(struct MyClass* mc)
/* {
Result *result = nullptr;
try {
result = new Result;
*result = mc->GetResult();
return result;
}
catch (...) {
delete result;
return nullptr;
}
} */
void FreeResult(struct Result* r)
/* { delete r; } */
#ifdef __cplusplus
} // end of extern "C"
#endif
I am attempting to write a C wrapper for some C++ data structures. Right now I've got the following in foo.cpp
typedef std::map<unsigned int, void *> _Map;
extern "C"{
void* map_create()
{
return reinterpret_cast<void*> (new _Map);
}
void map_put(void *map, unsigned int k, void *v)
{
Map *m = reinterpret_cast<_Map *> (map);
m->insert(std::pair<unsigned int, void *>(k, v));
}
}
In foo.h I've got
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *Map;
EXTERNC void *map_create();
EXTERNC void map_put(void* map, unsigned int k, int v);
I include foo.h and I'm good to go.
Now, I wanted to iterate over a map and noticed C++ does that through iterators. I have no experience with C++ and don't know how iterators are implemented.
Can I iterate over a std::map using a C wrapper? How would these functions definitions look like and how would I use them in a for-loop in my C code?
You won't be able to use iterators directly. You can, of course, do something along the lines of creating/releasing objects and obtain the values somehow. It isn't going to be efficient, though. It would look something like this:
typedef std::map<unsigned int, void*> map_type;
typedef map_type::iterator map_iterator;
void* map_iterator_create(void* map) {
return new map_iterator(map.begin());
}
void map_iterator_destroy(void* it) {
delete static_cast<map_iterator*>(it);
}
int map_iterator_next(void* map, void* it, unsigned int* key, void** value) {
map_iterator* mit = static_cast<map_iterator*>(it);
if (static_cast<map_type*>(map)->end() == *mit) {
return 0; // no more elements
}
*key = mit->first;
*value = mit->second;
++mit;
return 1;
}
This particular approach does reduce the flexibility coming with iterators a bit (e.g., it doesn't support subranges) but these could be supported at different costs. You'd use this iterator approach like this:
void* it = map_iterator_create(map);
unsigned int key;
void* value;
while (map_iterator_next(map, it, &key, &value)) {
printf("key=%d value=%p\n", key, value);
}
map_iterator_destory(it);
It is probably more reasonable to not expose the iterator interface but rather an interface iterating over the sequence, e.g.:
extern "C" { typedef void (*map_function)(unsigned int, void*, void*); }
void map_iterate(void* map, map_function fun, void* userdata) {
map_type* m = static_cast<map_type*>(m);
std::for_each(m->begin(), m->end(),
[=](map_type::value_type const& v) {
fun(v.first, v.second, userdata);
});
}
... which would be used as
void my_iterating_fun(unsigned int key, void* value, void* userdata) {
printf("key=%d value=%p\n", key, value);
}
// ...
map_iterator(map, my_iterating_fun, 0);
I haven't tried to compile the code (i.e., it is probably riddled with small typos) but something along those lines should work.
Here's something that won't compile, but gives you an idea on how I'd do it
class MyIterator {
public:
MyIterator(Map map) {
it = map.begin();
}
void advance() {
++it;
}
bool isValid() {
return it != map.end();
}
private:
Map::const_iterator it;
const Map map;
};
extern "C" {
void* newIterator(void* map) {
return new MyIterator(static_cast<Map>(map));
}
void freeIterator(void* it) {
delete static_cast<Map>(map);
}
void advanceIterator(void* it) {
static_cast<MyIterator>(it)->advance();
}
void isValid(void* it) {
static_cast<MyIterator>(it)->isValid();
}
int getKey(void* iterator) {...}
void* getValue(void* iterator) {...}
}
I have a strange problem that rarely happens relating to invalidated STL iterators that I've simplified in the example code below.
Foo.h
#include "Bar.h"
#include <map>
class Foo
{
std::map<int, Bar*> test;
public:
Foo() {}
void Update();
void AddEntry(int i, Bar* bar);
void DeleteEntry(int i);
};
Foo.cpp
#include "Foo.h"
void Foo::Update() {
for(auto iter = test.rbegin(); iter != test.rend(); iter++) {
iter->second->DoThingOne();
iter->second->DoThingTwo(); // BREAKS ON 2nd ITERATION
}
}
void Foo::AddEntry(int i, Bar* b) {
test[i] = b;
}
void Foo::DeleteEntry(int i) {
delete test[i];
test.erase(i);
}
Bar.h
class Foo;
class Bar
{
Foo* f;
static int count;
public:
friend class Foo;
Bar(Foo* f_);
void DoThingOne();
void DoThingTwo();
};
Bar.cpp
#include "Bar.h"
#include "Foo.h"
int Bar::count = 0;
Bar::Bar(Foo* f_) : f(f_) {}
void Bar::DoThingOne() {
if(count++ == 1) {
f->DeleteEntry(3);
}
}
void Bar::DoThingTwo() {
// Does things
}
Main.cpp
#include "Foo.h"
int main() {
Foo* foo = new Foo();
Bar* one = new Bar(foo);
Bar* two = new Bar(foo);
Bar* three = new Bar(foo);
foo->AddEntry(1, one);
foo->AddEntry(2, two);
foo->AddEntry(3, three);
foo->Update();
return 0;
}
So basically, when Foo::Update is called, the 1st iteration of the loop proceed normally, then the 2nd iteration calls DoThingOne which deletes the entry in the map that the previous iteration of the loop just used. When DoThingTwo is called right after I get a "Debug Assertion Failed! Expression: map/set iterator not decrementable" error crashing the program.
From what I understand, iterators over maps and sets are always valid except for iterators referring to elements removed, but here the iterator is referring to the element right after the one removed. My only guess is that it has something to do with the element being removed being the first/last element and the iterator in use is then referring to the new first/last element, but I still can't find out exactly why this is happening or how to work around it. I only really have the option of detecting when this happens in the for-loop before DoThingTwo is called and trying to fix it there.
Edit: After looking at the link provided by Nemo, I changed the loop to the following and it seems to work:
void Foo::Update {
auto iter = test.end();
for(iter--; iter != test.begin(); iter--) {
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
It looks really sloppy, but this does get the job done. Since using iterator instead of reverse_iterator works, I guess it does have something to do with how reverse_iterator works compared to iterator.
i need to register to a callback function provided by a third party dll, this function does not accept any arguments, and hence i cannot pass in the "this" to it. here the pData is the just the data.
//This is declared as static function in my class
void CMyClass::ThirdPartyCallBack(void *pData)
{
//How to access the member variables of the class
}
how to do this without using a global variable, appreciate you attention and time
A void* is a pointer to whatever you like. You can pass anything you like as the data pointer to the dll, for example "this". And in your callback, you convert it back to an object pointer.
You can create a table of context pointers that is associated with a table of 'thunks' that are used as the callback function(s) you give to the DLL:
class foo {
public:
void callback(void* data);
};
enum {
kMAX_CALLBACKS = 3,
};
foo* context_table [kMAX_CALLBACKS] = {
0,
0,
0
// however many you might need...
};
extern "C" void callback_0( void* data)
{
foo* ctx = context_table[0];
ctx->callback(data);
}
extern "C" void callback_1( void* data)
{
foo* ctx = context_table[1];
ctx->callback(data);
}
extern "C" void callback_2( void* data)
{
foo* ctx = context_table[2];
ctx->callback(data);
}
// ....
extern "C" {
typedef void (*dll_callback)(void*);
}
dll_callback callback_table[kMAX_CALLBACKS] = {
callback_0,
callback_1,
callback_2
// however many you might need...
};
dll_callback set_callback_context(foo* ctx)
{
for (int i =0; i < kMAX_CALLBACKS; ++i) {
if (context_table[i] == 0) {
context_table[i] = ctx;
return callback_table[i];
}
}
return 0;
}
void clear_callback_context(foo* ctx)
{
for (int i =0; i < kMAX_CALLBACKS; ++i) {
if (context_table[i] == ctx) {
context_table[i] = 0;
return;
}
}
}
Now when you need to set up a callback to foo::callback() pass the DLLs function that sets up the callback with something like:
third_party_set_callback( set_callback_context(foo_instance_ptr));
and the callback will end up at foo:callback() with the appropriate this pointer.
For this project, I cannot use C++11, or add any additional dependencies (e.g. Boost).
What I'm trying to achieve is this:
typedef void (*processorFunction)(int numItems, std::string* items);
class Files
{
public:
Files() : m_KVSeparator('='), m_ListSeparator(',') {}
~Files() {}
void ReadDataFile(std::string filename, std::map<std::string, processorFunction> processorFunctions);
char m_KVSeparator;
char m_ListSeparator;
};
void Files::ReadDataFile(std::string filename, std::map<std::string, processorFunction> processorFunctions)
{
// The file parsing and choosing of the function omitted for brevity:
processorFunction processor = ...;
int numItems = ...;
std::string* items = ...;
processor(numItems, items);
}
// Example parser:
void time_limit_parser(int& timeLimit, int numItems, std::string* items)
{
timeLimit = atoi(items[0].c_str());
}
int main()
{
// Omitted getting the global file manager pointer
Files* files = ...;
std::map<std::string, processorFunction> configProcessorFunctions;
int timeLimit;
// ****** WHAT GOES HERE? ******
files->ReadDataFile("config.dat", configProcessorFunctions);
}
My question is what do I put on the ****** WHAT GOES HERE? ****** line? I would use std::bind to partially apply it (a la time_limit_parser(timeLimit)), but I can't use C++11 for this project.
You wouldn't be able to do what you wanted even with bind because bind doesn't return function pointers. Instead, you'd have to use the std::function template to wrap them.
As it turns out, there's nothing preventing you from doing exactly that yourself.
struct BaseProcessor
{
virtual void operator()(int numItems, std::string* items) = 0;
};
struct TimeLimitParser : public BaseProcessor
{
int& timeLimit;
TimeLimitParser(int& limit)
: timeLimit(limit)
{}
virtual void operator()(int numItems, std::string* items)
{
time_limit_parser(timeLimit, numItems, items);
}
};
int main()
{
// Omitted getting the global file manager pointer
Files* files = ...;
std::map<std::string, processorFunction*> configProcessorFunctions;
int timeLimit;
TimeLimitParser parser(timeLimit);
configProcessorFunctions["foo"] = &parser;
files->ReadDataFile("config.dat", configProcessorFunctions);
}
Obviously you need to change the definition of processFunction to match a pointer/reference to BaseProcessor, and it's clearly not quite as pretty as using bind or lambdas, but if you can't upgrade or get boost that's about as good at it'll get without some serious wizardry.