糾結的CLI C++與Native C++的交互
最近在寫點東西,涉及到了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;