C如何回调C++的函数?如果回调函数中有C有C++调用其他C++函数的代码该如何?

bandaoyu 2018-01-16 04:13:42
有个C库clib.a要给php调用,并且给C库一个回调函数,因为php无法直接调用C库,所以我用第三方库C++库,PHP-CPP给php写了一个扩展


(C库回调PHP函数确实是很蛋疼的需求,但是没办法,需求在那里也只能想办法满足了)



C++库中调用C库的函数myComm:



Php::Value InitComm(Php::Parameters ¶meters)
{

SERVERINFO_PARAM ServerInfoParam[1]=
{
{0,"127.0.0.1",6000,callback_for_c}
};


relt = myComm(ServerInfoParam);

return relt;

}

myComm说明:
myComm(ServerInfoParam);

ServerInfoParam是个结构体,



typedef ubool (*FN_HANDLER) (int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen);

typedef struct tagSERVERINFO
{
int32 lServerID;
int8 pcServerIpAddr[64];
int32 lServerPort;
FN_HANDLER fnMsgHandler; //函数指针
}SERVERINFO_PARAM;




要给C库一个回调函数,C库无法直接调用C++函数,所以我写了一个callback_for_c函数,按C编译给函数指针fnMsgHandler用



extern "C" {

int32 callback_for_c(int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen)
{

Php::Value relt;
printf(“call callback_for_c sucess!\n");
// call a function from user space
Php::Value data = Php::call("some_function","some_parameter");

return int32_t(relt);
}

}




callback_for_c函数通过PHP-CPP库提供的函数Php::call回调PHP的函数,目的是想通过这样的方式(C库回调callback_for_c,callback_for_c中调Php::call,Php::call调some_function)
达到C库回调php函数的目的。

php中的函数:

// define a user space function
//这个函数会放在php端,由PHP人员自己往里面添加自己的函数代码
function some_function($param)
{

//***


**//
echo("userspace function called with $param\n");
}


但是运行函数时,函数在运行到Php::Value data = Php::call("some_function","some_parameter"); 段错误。

gdb信息如下:



(gdb) bt
#0 0x006c19f0 in _emalloc ()
#1 0xb6f57374 in zend_string_alloc (persistent=0, len=13) at /usr/include/php-zts/php/Zend/zend_string.h:122
#2 zend_string_init (persistent=0, len=13, str=0xb6ff0181 "some_function") at /usr/include/php-zts/php/Zend/zend_string.h:158
#3 Php::Value::Value (this=0xb4f4fdd0, value=0xb6ff0181 "some_function", size=-1) at zend/value.cpp:121
#4 0xb6fdbace in callback_for_c () from /usr/lib/php-zts/modules/clientcomm.so
#5 0xb6fe2de3 in RecvCommMultiFrameFinishProcess (lCommModleID=1, ulIdentifyCode=1, unMsgType=62, pstDataBuff=0xb44ff01c "\023",
lDataLen=124) at clientsrv.c:161
#6 0xb6fe2937 in ServerSingleFrameProcess (lModuleID=1, pstFrameHead=0xb44ff010 "\237", <incomplete sequence \371\204>,
pMsgBuff=0xb44ff01c, lMsgLen=124) at clientsprot.c:63
#7 0xb6fe2b2e in ClientFrameProcess (_this=0xb4600610, pFrameHead=0xb44ff010 "\237", <incomplete sequence \371\204>, lFrameLen=136,
lFrameType=3) at clientsprot.c:142
#8 0xb6fef653 in ParserProcessData (_this=0xb4600610, pstParser=0xb6ff4d80 <s_stHwntpProtParser>,
fnProcFrame=0xb6fe2a1f <ClientFrameProcess>) at ../src/mngrtutil.c:158
#9 0xb6fe23a4 in TryClientRecvProcess (_this=0xb4600610) at clientcomm.c:119
#10 0xb6fe27f4 in ClientOnTimer (_this=0xb4600610) at clientcomm.c:365
#11 0xb6fee560 in TryProcEachModule (pstModuleMgr=0xb46005d0) at ../src/modulemgr.c:439
#12 0xb6fee66c in ExecModuleMgr (pstModuleMgr=0xb46005d0) at ../src/modulemgr.c:498
#13 0xb6fdf20b in ExecModules (lServerNum=1) at hwmain.c:171
#14 0xb6fdf24a in hw_main (argc=1, argv=0x0) at hwmain.c:194
#15 0xb6fde7d5 in HwCommModuleManager (arg=0xb6ff4bc0 <s_astFunctionParam>) at hwclientcomm.c:164
#16 0xb7aed577 in start_thread () from /lib/libpthread.so.0
#17 0xb746c076 in clone () from /lib/libc.so.6
(gdb)


是不是因为虽然我把函数Php::call("some_function","some_parameter")放在callback_for_c里面并且编译通过,但是在调用call和call调用some_function
都是C库中执行,也就是目标库执行,而目标库是按C的方式执行,而some_function函数是通过PHP-CPP库转成C++函数的,所以C库一旦调用some_function就出错?

有什么办法能解决我的这个问题吗?

PHP-CPP库的资料和源代码在这里可以获取:
http://www.php-cpp.com/


下面是它的例子:

http://www.php-cpp.com/documentation/calling-functions-and-methods


...全文
691 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Saleayas 2018-01-18
  • 打赏
  • 举报
回复
我比较认为是内存错误的原因。 你直接从 php->C++->C 然后回来,不要执行任何其他的代码,仅仅测试这个框架流程。 看原因是分配字符串到 php::Value 的问题。 你可以尝试自己先分配一个内存空间试试。
赵4老师 2018-01-18
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话,文本文件的格式问题可参考json或xml 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·…… “跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边, 回头是“使用共享纯文本文件进行信息交流”的岸! 无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
bandaoyu 2018-01-17
  • 打赏
  • 举报
回复
引用 7楼paschen 的回复:
调用约定可能不一致,建议都使用_stdcall
嗯,由于php::call是php-cpp库实现的,估计要改库才可以,我分析的对吗
fly_with_the_winds 2018-01-17
  • 打赏
  • 举报
回复
extern "C" { int32 callback_for_c(int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen) { Php::Value relt; printf(“call callback_for_c sucess!\n"); // call a function from user space Php::Value data = Php::call("some_function","some_parameter"); return int32_t(relt); } } 上面这段代码你用C编译器编译还是C++编译器呢?
bandaoyu 2018-01-17
  • 打赏
  • 举报
回复
引用 9楼fly_with_the_winds 的回复:
extern "C" { int32 callback_for_c(int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen) { Php::Value relt; printf(“call callback_for_c sucess!\n"); // call a function from user space Php::Value data = Php::call("some_function","some_parameter"); return int32_t(relt); } } 上面这段代码你用C编译器编译还是C++编译器呢?
c++
paschen 版主 2018-01-16
  • 打赏
  • 举报
回复
调用约定可能不一致,建议都使用_stdcall
赵4老师 2018-01-16
  • 打赏
  • 举报
回复
bandaoyu 2018-01-16
  • 打赏
  • 举报
回复
引用 4楼幻夢之葉 的回复:
int32 __declspec(dllexport) callback_for_c(int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen) 修改为以上再试试看?
调用callback_for_c没有问题哈,是执行到它里面的php::call这句出错的,因为我在它里面php::call前面加了一句打印信息,信息打印出来了。
幻夢之葉 2018-01-16
  • 打赏
  • 举报
回复
int32 __declspec(dllexport) callback_for_c(int32 lIdentifyCode,int16 nMsgType,void *pstMsg,int32 lMsgLen) 修改为以上再试试看?
bandaoyu 2018-01-16
  • 打赏
  • 举报
回复
引用 2楼幻夢之葉 的回复:
肯定不是你猜测的原因! Php::Value data = Php::call("some_function","some_parameter"); 你可以换个some_function,只打印一句话的函数试试
那个函数是例子里面函数,没有问题的。而且我试了只打印,也是死掉了。而我吧php::call放到c++环境中,也就是不是在c的回调callback_for_c里面就执行正常,所以我怀疑是c库无法调用c++的函数
幻夢之葉 2018-01-16
  • 打赏
  • 举报
回复
肯定不是你猜测的原因! Php::Value data = Php::call("some_function","some_parameter"); 你可以换个some_function,只打印一句话的函数试试
bandaoyu 2018-01-16
  • 打赏
  • 举报
回复
PHP-CPP库的资料和源代码在这里可以获取: http://www.php-cpp.com/ 下面是它的例子: http://www.php-cpp.com/documentation/calling-functions-and-methods <?php // define a user space function function some_function($param) { echo("userspace function called with $param\n"); } // example input $input = array( 'x' => 10, 'y' => 20, 'z' => 30 ); example_function($input, function($param1, $param2) { echo("lambda function called with param $param1 $param2\n"); }); ?> #include <phpcpp.h> #include <iostream> /** * Native function that is callable from PHP * * This function gets two parameters: an associative array and a callback. * It does not do anything meaningful, it is just a demonstration function. * * @param params The parameters passed to the function */ void example_function(Php::Parameters ¶ms) { // first parameter is an array Php::Value array = params[0]; // call the PHP array_keys() function to get the parameter keys std::vector<std::string> keys = Php::array_keys(array); // loop through the keys for (auto &key : keys) { // output key Php::out << "key: " << key << std::endl; } // call a function from user space Php::Value data = Php::call("some_function", "some_parameter"); // create an object (this will also call __construct()) Php::Object time("DateTime", "now"); // call a method on the datetime object Php::out << time.call("format", "Y-m-d H:i:s") << std::endl; // second parameter is a callback function Php::Value callback = params[1]; // call the callback function callback("some","parameter"); // in PHP it is possible to create an array with two parameters, the first // parameter being an object, and the second parameter should be the name // of the method, we can do that in PHP-CPP too Php::Array time_format({time, "format"}); // call the method that is stored in the array Php::out << time_format("Y-m-d H:i:s") << std::endl; } /** * Switch to C context, because the Zend engine expects get get_module() * to have a C style function signature */ extern "C" { /** * Startup function that is automatically called by the Zend engine * when PHP starts, and that should return the extension details * @return void* */ PHPCPP_EXPORT void *get_module() { // the extension object static Php::Extension extension("my_extension", "1.0"); // add the example function so that it can be called from PHP scripts extension.add("example_function", example_function); // return the extension details return extension; } }

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧