我的问题是如何将C ++与Vala接口,这对我来说是一个非常基本和基本的问题,特别是在内存,修改数据结构和类型安全方面。
通常的答案是:
问题是C它甚至不接近C ++所能提供的,而且90%的时间它只是不同的语言;另一方面,Glib的问题在于它不是标准的,它也不是C ++,我在C ++中有很多代码,我想以安全的方式重用,加上C ++编码对我来说更有效。< / p>
那么当我想将std::vector<T>
传递给Vala或stringstream
时会发生什么?当我的Vala程序想要复制,引用,编辑和调整/重新定位该容器时会发生什么?
我不知道Vala如何处理这个因为vapi和Vala的底线是关于C的,我找不到任何关于如何处理C ++代码的具体答案。
考虑到我已经放弃了GTKmm作为一个真正的选择,你怎么建议我应该使用Vala&amp; amp; C ++?
答案 0 :(得分:3)
Vala不支持C ++。你无法找到关于如何处理C ++代码的答案的原因是没有 - 你不会。
从Vala获取C ++库的唯一方法是首先在C中编写一个包装器。如果你愿意,那个包装器可以使用GLib - Vala需要GLib,所以如果你计划使用GLib作为C API的唯一消费者,Vala并不真正添加依赖。或者你可以为std :: vector或stringstream编写C绑定。
如果您想要C ++库的C包装器示例,请查看Snappy或LevelDB。它们都是很好的例子,说明创建一个简单的C包装器是多么容易,虽然从API的角度来看,恕我直言并不是特别好(实际上,我不认为C ++ API特别好,但我觉得这样关于大多数C ++ API ...)。
如果您希望保留处理所有类型的能力,那么您不会在C API中获得C ++模板的类型安全性。您将不得不在C API中使用void *(或类似的东西,如gpointer),但您可以使用正确的绑定在Vala中获得类型安全性。例如,如果我想为std :: vector创建绑定,则C API的一部分可能看起来像
/* 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
和
/* 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);
}
(如果你不想使用glib,你可以创建一个类似的typedef,而不是使用GDestroyNotify。)
然后,在VAPI中
[Compact]
public class Vector<T> {
[CCode (simple_generics = true)]
public Vector ();
public void push_back (owned T value);
public owned T pop_back ();
}
这个问题是它只适用于可以填充在指针中的类型。从C方面来看,这基本上就是如何完成的,但是如果你需要绑定类似std :: vector的东西,你需要为那个类型创建一个专门的绑定,或者你的API有点像GArray,其中你必须传递大小(这些不从Vala使用起来很有趣。)