Pinvoke question: How to structure callback that includes a buffer

G

Guest

We are using a 3rd party API that processes video stream files to update a
data structure in the file. I am writting a C# facade for this API but I am
having a hard time getting it to pass data correctly. Can someone please
check out the approach I am using and give me some advice?

The API is structured where I initialize it by passing in two callback
methods. These methods in my C# code are called by the API to read and write
buffers from the input or output files. When I populate the "get" buffer in
the GetStreamBuf method I should see that same buffer in the subsequent
PutStreamBuf callback, but the PutStreamCallback appears to recieve an empty
buffer, as though the GetStreamBuf didn't really popultate the buffer.


//API Initialization
public delegate Int32 GetStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);
public delegate Int32 PutStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);

[DllImport("tableprocessor.dll", CharSet = CharSet.Ansi, EntryPoint = "#33",
CallingConvention=CallingConvention.StdCall)]
private static extern int InitProcessor(
GetStreamBufCallback GsCb,
PutStreamBufCallback PsCb,
Boolean enableLogging,
Int32 logLevel,
String logFile
);



//Callback methods
System.IO.FileStream fsInput;
Byte[] sharedGetBuf = new Byte[PACKET_SIZE]; //Allocate buffer
Byte[] sharedPutBuf = new Byte[PACKET_SIZE]; //Allocate buffer

public Int32 GetStreamBuf(Byte[] buf, Int32 bufSize)
{
if (fsInput != null)
{
if (fsInput.Read(sharedGetBuf, 0, bufSize) ==
TpFacade.PACKET_SIZE)
{
buf = sharedGetBuf;
return SUCCESS; //return callback status
to API
}
}
}


public Int32 PutStreamBuf(Byte[] buf, Int32 bufSize)
{
sharedPutBuf = buf;
//...
return SUCCESS; //Success == 0

}
 
G

Guest

And the call to initialize the API
if (TpFacade.InitProcessorFacade(GetStreamBuf, PutStreamBuf,
m_EnableLogging, m_LogLevel, apiLogFileString))
{ return; }

Thanks for any help!
 
M

Mattias Sjögren

Tom,
//API Initialization
public delegate Int32 GetStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);
public delegate Int32 PutStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);

The runtime can't know how bit those buffers are unless you tell it.
Try adding the attribute [MarshalAs(UnmanagedType.LPArray,
SizeParamIndex=1)] to the Buf parameters.

public Int32 GetStreamBuf(Byte[] buf, Int32 bufSize)
{
if (fsInput != null)
{
if (fsInput.Read(sharedGetBuf, 0, bufSize) ==
TpFacade.PACKET_SIZE)
{
buf = sharedGetBuf;

Here you're just changing which array the local buf parameter refers
to. It will not change the content of the buffer that is passed to
you. You have to copy the data into buf (or read into it directly)
instead.


Mattias
 
G

Guest

Thanks, Mattias! That helps a lot. I'm not out of the woods, yet, but I'm
on my way... :)
--
Regards,
Tom Allen


Mattias Sjögren said:
Tom,
//API Initialization
public delegate Int32 GetStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);
public delegate Int32 PutStreamBufCallback([In, Out] Byte[] Buf, Int32
buf_len);

The runtime can't know how bit those buffers are unless you tell it.
Try adding the attribute [MarshalAs(UnmanagedType.LPArray,
SizeParamIndex=1)] to the Buf parameters.

public Int32 GetStreamBuf(Byte[] buf, Int32 bufSize)
{
if (fsInput != null)
{
if (fsInput.Read(sharedGetBuf, 0, bufSize) ==
TpFacade.PACKET_SIZE)
{
buf = sharedGetBuf;

Here you're just changing which array the local buf parameter refers
to. It will not change the content of the buffer that is passed to
you. You have to copy the data into buf (or read into it directly)
instead.


Mattias
 
Top