2014-07-15 21 views
2

我使用FFMPEG在C#,並具有以下功能prototpe:的IntPtr到回調函數

public static extern AVIOContext* avio_alloc_context(byte* buffer, int buffer_size, int write_flag, void* opaque, IntPtr read_packet, IntPtr write_packet, IntPtr seek); 

在C/C++此函數被聲明如下:

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)) 

在C/C++我可以執行以下操作來調用這個函數:

int readFunction(void* opaque, uint8_t* buf, int buf_size) 
{ 
    // Do something here 
    int numBytes = CalcBytes(); 
    return numBytes; 
} 

int64_t seekFunction(void* opaque, int64_t offset, int whence) 
{ 
    // Do seeking here 
    return pos; 
} 

AVIOContext * avioContext = avio_alloc_context(ioBuffer, ioBufferSize, 0, (void*)(&fileStream), &readFunction, NULL, &seekFunction); 

readFunctionseekFunction是CAL用於讀取/搜索等的lback函數。

我不確定如何在C#版本的代碼中複製此行爲,當它期望IntPtr。我如何創建回調函數並將它們傳遞給C#版本?

回答

0

原來你可以做到這一點,但它並不完全直觀。

首先你需要創建一個UnmanagedFunctionPointer委託並確保PARAMS可以使用[In, Out]

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
public delegate int av_read_function_callback(IntPtr opaque, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), In, Out] byte[] endData, int bufSize); 

在函數,那麼我們可以名帥這個delegate被修改後,由被叫方來電者通過 回如下:

private av_read_function_callback mReadCallbackFunc; 

mReadCallbackFunc = new av_read_function_callback(ReadPacket); 

mAvioContext = FFmpegInvoke.avio_alloc_context(mReadBuffer, mBufferSize, 0, null, Marshal.GetFunctionPointerForDelegate(mReadCallbackFunc), IntPtr.Zero, IntPtr.Zero); 

其中ReadPacket看起來像

public int ReadPacket(IntPtr opaque, byte[] endData, int bufSize) 
{ 
    // Do stuff here 
} 

這會導致與C++中的函數指針相同的行爲。