纠结的CLI C++与Native C++的交互

时间:2022-11-04 17:50:11

最近在写点东西,涉及到了CLR C++与Native C++的互相调用的问题,结果...........纠结啊。

交互原型

交互原型是这样的:

void* avio_alloc_context(
unsigned
char *buffer,
int buffer_size,
int write_flag,
void *opaque,
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
int64_t (
*seek)(void *opaque, int64_t offset, int whence));

第一次尝试

public ref class test
{
int Writebuffer(void *opaque,libffmpeg::uint8_t* buf, int buf_size){
}

main()
{
test testobj
=gcnew test();
libffmpeg::avio_alloc_context(outbuffer,
32768,0,NULL ,NULL,testobj->Writebuffer ,NULL);
}

结果报错,要求创建指向成员的指针。

第二次尝试

使用了委托,然后使用  Marshal::GetFunctionPointerForDelegate获取函数指针结果....

编译不报错了,运行时回调倒是有了,可回调函数return后就报错..........估计是对象回收或者是非法访问导致。

第三次尝试

直接构造了静态函数

int static Writebuffer(void *opaque,libffmpeg::uint8_t* buf, int buf_size)

这个可以正常回调了,运行也不报错,可我需要的对象在静态函数中可获取不到(为了多线程考虑,不能用全局对象)。

于是需要传入 void *opaque 参数。

但是这个要传的是一个托管对象,咋办呢?使用pin_ptr,嗯,可以传进去。

呃,新的问题来了,void *怎转回托管对象呢?好吧,这个我是没找到合适的办法,

再次失败.........

第四次尝试

找到了gcroot<>这个模版,必须有这个:#include<vcclr.h> 

代码:

public ref class test
{
gcroot
<BinaryWriter^> _writedStream;
int static Writebuffer(void *opaque,libffmpeg::uint8_t* buf, int buf_size){
}

好吧,斜体部分报错,说是托管类中不能使用非托管对象........

再改:

gcroot<BinaryWriter^>* _writedStream;

这次不报错了。

继续:

Open( BinaryWriter^ writer)
{
*_writedStream=writer;
}

结果运行时告诉我找不到对象....好吧,还需要初始化:

_writedStream=new gcroot<BinaryWriter ^>;
*_writedStream=writer;

这次终于木有问题了............

avio_alloc_context(outbuffer, 32768,0,this->_writedStream ,NULL,this->Write_buffer ,NULL);

Write_buffer(
void *opaque,libffmpeg::uint8_t* buf, int buf_size){
array
<unsigned char>^ mbuf=gcnew array<unsigned char>(buf_size);
System::Runtime::InteropServices::Marshal::Copy((IntPtr)buf,mbuf,
0,buf_size);
gcroot
<BinaryWriter ^>* wr=(gcroot<BinaryWriter ^>*) opaque;
BinaryWriter
^writeStream= *wr;
writeStream
->Write(mbuf,0,buf_size);
writeStream
->Flush();
return 0;
}

总结

就俩字:坑爹