Reputation: 9811
My problem is how to interface C++ with Vala, a really basic and fundamental problem for me, especially when it comes to memory, modifying data structures and type safety.
The usual answers are about things like :
The problem is that C it's not even close to what C++ can offer, and it's just different language 90% of the time; on the other hand the problem with Glib is that it's not standard and it's not C++ either and I have a lot of code in C++ that I would like to reuse in a safe way, plus coding in C++ is way more effective for me.
So what happens when I want to pass an std::vector<T>
to Vala or a stringstream
? What happens when my Vala program wants to copy, reference, edit and resize/relocate that container ?
I don't know how Vala handles this because vapi and the bottom line of Vala is about C, and I can't find any specific answer about how to deal with C++ code.
Considering that I already discarded GTKmm as a real option, How do you suggest I should go with Vala & C++ ?
Upvotes: 1
Views: 176
Reputation: 17522
Vala does not support C++. The reason you can't find an answer about how to deal with C++ code is that there isn't one--you don't.
The only way to get a C++ library to work from Vala is to write a wrapper in C first. That wrapper can use GLib if you want--Vala requires GLib anyways so if you're planning on Vala software being the sole consumer of the C API using GLib doesn't really add a dependency. Or you can write C bindings for std::vector or stringstream.
If you want examples of C wrappers for C++ libraries, take a look at Snappy or LevelDB. They are both pretty good examples of how easy it is to create a simple C wrapper, though IMHO neither is particularly good from an API perspective (actually, I don't think the C++ APIs are particularly good, but I feel that way about most C++ APIs...).
You're not going to get type safety for C++ templates in a C API if you want to retain the ability to handle all types. You're going to have to use void* (or something similar, like gpointer) in the C API, but you can get the type safety back in Vala with the right bindings. For example, if I wanted to create a binding for std::vector, part of the C API might look like
/* foo-vector.h */
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*FooDestroyNotify) (void* data);
typedef struct _FooVector FooVector;
FooVector* foo_vector_new (FooDestroyNotify destroy_notify);
void foo_vector_free (FooVector* vec);
void foo_vector_push_back (FooVector* vec, void* value);
void* foo_vector_pop_back (FooVector* vec);
#ifdef __cplusplus
}
#endif
And
/* foo-vector.cpp */
#include <iostream>
#include <vector>
#include <stdlib.h>
struct _FooVector {
std::vector<void*>* vec;
FooDestroyNotify destroy_notify;
};
FooVector* foo_vector_new (FooDestroyNotify destroy_notify) {
FooVector* vec = (FooVector*) malloc (sizeof (FooVector));
vec->vec = new std::vector<void*>;
vec->destroy_notify = destroy_notify;
return vec;
}
void foo_vector_push_back (FooVector* vec, void* value) {
vec->vec->push_back (value);
}
void* foo_vector_pop_back (FooVector* vec) {
void* res = NULL;
if (!vec->vec->empty ()) {
res = vec->vec->back ();
vec->vec->pop_back ();
}
return res;
}
void foo_vector_free (FooVector* vec) {
if (vec->destroy_notify != NULL) {
std::vector<void*>::iterator it = vec->vec->begin ();
for (; it < vec->vec->end () ; it++) {
vec->destroy_notify (*it);
}
}
delete vec->vec;
free (vec);
}
(If you don't want to use glib you can just create a similar typedef instead of using GDestroyNotify.)
Then, in a VAPI
[Compact]
public class Vector<T> {
[CCode (simple_generics = true)]
public Vector ();
public void push_back (owned T value);
public owned T pop_back ();
}
The problem with this is that it only works with types which can be stuffed in a pointer. From the C side this is basically how things are done, but if you need to bind something like std::vector you'll need to either create a specialized binding for that one type or model your API a bit like GArray, where you have to pass around sizes (which will not be fun to use from Vala).
Upvotes: 4