调用C++;C程序中的共享库…如何管理? 我想为C++框架写一个包装器。这个框架有点笨拙,而且不是很好,而且是C++的。因此,我希望能够通过使用一个共享库,从他们框架的外部(通过良好的旧C文件)调用他们的方法。这听起来像是需要一个包装器来封装想要的框架方法,用C代替C++。
到目前为止还不错。。。。以下是我已经做过的: 接口aldebaran.h (这在我的include文件夹中,应该从框架外部调用超声波方法): 现在,包装器: cpp文件aldebaran.cpp:调用C++;C程序中的共享库…如何管理? 我想为C++框架写一个包装器。这个框架有点笨拙,而且不是很好,而且是C++的。因此,我希望能够通过使用一个共享库,从他们框架的外部(通过良好的旧C文件)调用他们的方法。这听起来像是需要一个包装器来封装想要的框架方法,用C代替C++。,c++,c,C++,C,到目前为止还不错。。。。以下是我已经做过的: 接口aldebaran.h (这在我的include文件夹中,应该从框架外部调用超声波方法): 现在,包装器: cpp文件aldebaran.cpp: #include <stdio.h> #include <stdlib.h> #include <string.h> #include "aldebaran.h" #include "alproxy.h" #include "../../include/aldeb
#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);
}
#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
这里的问题是,如果没有所有代理的实例化,就无法调用subscribe_超声波()之类的函数。。。这是我们的先决条件:
...
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");
...
如果我没有调用上面的代码,其他所有代码都将失败
在他们的框架内,可以“自动加载”我的libaldebaran.so,通过类似以下调用的python脚本:
myModule = ALProxy("Aldebaran", global_params.strRemoteIP, global_params.nRemotePort );
然后,框架日志显示:
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 ______
这完全没关系。。。它调用了我的模块的构造函数(因此所有其他需要的代理也被实例化)
但是这个实例当然不属于我的C程序
也许有可能将此共享给所有其他进程?您说过要围绕OO框架创建一个C包装器API 这意味着您不需要任何对象通过包装器API(正如decribed头中显示的那样)。似乎所有需要的对象都是在包装器API后面创建/销毁的,不在测试程序的视野之内
第一种似乎是这样的。测试包装器API不需要对象。最后,所有对象都是通过一组固定函数访问的字节(内存中)。函数是作为成员函数(C++)编写还是作为普通C函数编写并不重要,只要它们符合对象的预期语义。您说过要围绕OO框架创建C包装器API 这意味着您不需要任何对象通过包装器API(正如decribed头中显示的那样)。似乎所有需要的对象都是在包装器API后面创建/销毁的,不在测试程序的视野之内
第一种似乎是这样的。测试包装器API不需要对象。最后,所有对象都是通过一组固定函数访问的字节(内存中)。函数是作为成员函数(C++)编写还是作为普通C函数编写并不重要,只要它们符合对象的预期语义。您可能需要采取稍微不同的方法。考虑这样的C接口:
#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
UltrasonHandle
结构故意不透明,因此您可以在实现中将其定义为您想要的任何形式。我做的另一个修改是添加类似于构造函数和析构函数的显式创建和销毁方法。实现将类似于:
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
}
}
关键是将C++的C++接口包通过自由函数公开OO概念,调用方明确地将对象指针(<代码>此代码/代码>)传递给函数,并以相同的方式显式地公开构造函数和析构函数。包装器代码几乎可以从那里机械地生成。另一个关键点是,您永远不会让异常向外传播,并避开全局对象实例。我不确定后者是否会给您带来痛苦,但我会担心施工/销毁排序问题。
您可能需要采取稍微不同的方法。考虑这样的C接口:#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
UltrasonHandle
结构故意不透明,因此您可以在实现中将其定义为您想要的任何形式。我做的另一个修改是添加类似于构造函数和析构函数的显式创建和销毁方法。实现将类似于:
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
}
}
关键是将C++的C++接口包通过自由函数公开OO概念,调用方明确地将对象指针(<代码>此代码/代码>)传递给函数,并以相同的方式显式地公开构造函数和析构函数。包装器代码几乎可以从那里机械地生成。另一个关键点是,您永远不会让异常向外传播,并避开全局对象实例。我不确定后者是否会引起你的悲痛,但我会担心构造/销毁排序问题。
< P>我不清楚你是否意识到这一点,但是如果你有C++代码来动态加载到你的程序中,然后你应该把你的程序和C++编译器链接起来,并且使你的主函数也成为C++函数——即使它和一样小。int main(int argc, char **argv)
{
return(real_main_in_c(argc, argv));
}
real\u main\u in_c()
函数就是您之前所称的main()
;它只是被重命名了。这确保了用于处理全局变量和静态变量初始化的C++机制被加载和操作。C++启动代码比C启动代码工作更多。动态加载C
这只是一个(小的)方面,但它是一个重要的实用的例子。
< P>我不清楚你是否意识到这一点,但是如果你有C++代码动态加载到你的程序中,那么你应该把你的程序与C++编译器连接起来,并且使你的主函数也是一个C++函数——即使它和一样小。int main(int argc, char **argv)
{
return(real_main_in_c(argc, argv));
}
real\u main\u in_c()
函数就是您之前所称的main()
;它只是被重命名了。这确保了用于处理全局变量和静态变量初始化的C++机制被加载和操作。C++启动代码比C启动代码工作更多。动态加载C
这只是一个(小的)