By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,723 Members | 1,407 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,723 IT Pros & Developers. It's quick & easy.

Please Help - P/Invoke and unmanaged types

P: n/a
Don
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don
Nov 16 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Don
Hi,

Thanks for your reply. I am still having some trouble, probably with
the 2nd parameter (LadybugImage* pimage). I declared the LadyBugImage
struct as a class in my C# code as follows:

[StructLayout(LayoutKind.Sequential)]
unsafe public class LadybugImage{
public UInt32 uiCols = 0;
public UInt32 uiRows = 0;
public LadybugVideoMode videoMode = new LadybugVideoMode();
public LadybugTimestamp timestamp = new LadybugTimestamp();
public LadybugImageInfo imageInfo = new LadybugImageInfo();
// public string pData = "";
unsafe public byte* pData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public UInt32[] ulReserved;
}

I suspect that the member pData is causing me grief, and/or the fact
that I used class instead of struct. Any suggestions here? If it
weren't for the complex structures, I think this would be pretty easy.

I couldn't help but notice that you substituted a 6 for LB_NUM_CAMERAS
when declaring pBuffer. Are you familiar with the LadyBug API? If so
are you using it w/ .NET?

Thanks again,
Don
"BMermuys" <so*****@someone.com> wrote in message news:<ud**************@TK2MSFTNGP09.phx.gbl>...
Hi,

You can't have a managed type that you can pass as such.

1. You can use a managed type and an unmanaged buffer and copy between them
after and/or before the function call.

* managed buffer:
byte [][] mBuffer = new byte[LB_NUM_CAMERAS][];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
mBuffer[i] = new byte[ LB_COLS * LB_ROWS * 4 ];

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* copy managed to unmanaged (eg before function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( mBuffer[i], 0, pBuffer[i], LB_COLS * LB_ROWS * 4 );

* copy unmanaged to managed (eg after function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( pBuffer[i], mBuffer[i], 0, LB_COLS * LB_ROWS * 4 );

* unmanaged function :

[DllImport(....) ]
ladybugConvertToMultipleBGRU32( ..., ... , IntPtr [] p, ... );

pBuffer is an IntPtr[] so pass it as the 3th parameter.

* cleanup unmanaged memory
for (int i= 0; i<LB_NUM_CAMERAS; ++i )
Marshal.FreeHGlobal ( pBuffer[i] );
2. _OR_ you can only use an unmanaged buffer and manipulate this with
properties or methods. This way you avoid copying. (You could put this in
a class and make sure there is access to pBuffer so you can call the
unmanaged function)

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* read data
public byte ReadData( int camera, int idx )
{
// TODO check if idx < rows*cols*4
return Marshal.ReadByte ( pBuffer[camera], idx );
}

* write data
public void WriteData( int camera, int idx, byte value )
{
// TODO check if idx < rows*cols*4
Marshal.WriteByte ( pBuffer[camera], idx, value );
}

HTH,
greetings
"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don

Nov 16 '05 #2

P: n/a
Hi,

"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
Hi,

Thanks for your reply. I am still having some trouble, probably with
the 2nd parameter (LadybugImage* pimage). I declared the LadyBugImage
struct as a class in my C# code as follows:

[StructLayout(LayoutKind.Sequential)]
unsafe public class LadybugImage{
public UInt32 uiCols = 0;
public UInt32 uiRows = 0;
public LadybugVideoMode videoMode = new LadybugVideoMode();
public LadybugTimestamp timestamp = new LadybugTimestamp();
public LadybugImageInfo imageInfo = new LadybugImageInfo();
// public string pData = "";
unsafe public byte* pData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public UInt32[] ulReserved;
}

I suspect that the member pData is causing me grief, and/or the fact
that I used class instead of struct. Any suggestions here? If it
I can only say that if the parameter is LadybugImage* then you can use a
class or a struct as ref parameter). Both are valid.
weren't for the complex structures, I think this would be pretty easy.

I couldn't help but notice that you substituted a 6 for LB_NUM_CAMERAS
when declaring pBuffer. Are you familiar with the LadyBug API? If so
Not at all. I just read your previous post. I did check the internet, found
the ladybug but no public information about the sdk.

If you want more help you should post all c structs (concerning the
function). Also some information about what pData suppose to do. Do you
need to fill it, does the dll fill it or does the dll just set a pointer to
allocated data.
Maybe some c code that demonstrates the complete use of the function, etc...

hth,
greetings
are you using it w/ .NET?

Thanks again,
Don
"BMermuys" <so*****@someone.com> wrote in message

news:<ud**************@TK2MSFTNGP09.phx.gbl>...
Hi,

You can't have a managed type that you can pass as such.

1. You can use a managed type and an unmanaged buffer and copy between them after and/or before the function call.

* managed buffer:
byte [][] mBuffer = new byte[LB_NUM_CAMERAS][];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
mBuffer[i] = new byte[ LB_COLS * LB_ROWS * 4 ];

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* copy managed to unmanaged (eg before function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( mBuffer[i], 0, pBuffer[i], LB_COLS * LB_ROWS * 4 );

* copy unmanaged to managed (eg after function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( pBuffer[i], mBuffer[i], 0, LB_COLS * LB_ROWS * 4 );

* unmanaged function :

[DllImport(....) ]
ladybugConvertToMultipleBGRU32( ..., ... , IntPtr [] p, ... );

pBuffer is an IntPtr[] so pass it as the 3th parameter.

* cleanup unmanaged memory
for (int i= 0; i<LB_NUM_CAMERAS; ++i )
Marshal.FreeHGlobal ( pBuffer[i] );
2. _OR_ you can only use an unmanaged buffer and manipulate this with
properties or methods. This way you avoid copying. (You could put this in a class and make sure there is access to pBuffer so you can call the
unmanaged function)

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* read data
public byte ReadData( int camera, int idx )
{
// TODO check if idx < rows*cols*4
return Marshal.ReadByte ( pBuffer[camera], idx );
}

* write data
public void WriteData( int camera, int idx, byte value )
{
// TODO check if idx < rows*cols*4
Marshal.WriteByte ( pBuffer[camera], idx, value );
}

HTH,
greetings
"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don

Nov 16 '05 #3

P: n/a
Hi,

You can't have a managed type that you can pass as such.

1. You can use a managed type and an unmanaged buffer and copy between them
after and/or before the function call.

* managed buffer:
byte [][] mBuffer = new byte[LB_NUM_CAMERAS][];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
mBuffer[i] = new byte[ LB_COLS * LB_ROWS * 4 ];

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* copy managed to unmanaged (eg before function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( mBuffer[i], 0, pBuffer[i], LB_COLS * LB_ROWS * 4 );

* copy unmanaged to managed (eg after function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( pBuffer[i], mBuffer[i], 0, LB_COLS * LB_ROWS * 4 );

* unmanaged function :

[DllImport(....) ]
ladybugConvertToMultipleBGRU32( ..., ... , IntPtr [] p, ... );

pBuffer is an IntPtr[] so pass it as the 3th parameter.

* cleanup unmanaged memory
for (int i= 0; i<LB_NUM_CAMERAS; ++i )
Marshal.FreeHGlobal ( pBuffer[i] );
2. _OR_ you can only use an unmanaged buffer and manipulate this with
properties or methods. This way you avoid copying. (You could put this in
a class and make sure there is access to pBuffer so you can call the
unmanaged function)

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* read data
public byte ReadData( int camera, int idx )
{
// TODO check if idx < rows*cols*4
return Marshal.ReadByte ( pBuffer[camera], idx );
}

* write data
public void WriteData( int camera, int idx, byte value )
{
// TODO check if idx < rows*cols*4
Marshal.WriteByte ( pBuffer[camera], idx, value );
}

HTH,
greetings
"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don

Nov 16 '05 #4

P: n/a
Don
Hi,

Thanks for your reply. I am still having some trouble, probably with
the 2nd parameter (LadybugImage* pimage). I declared the LadyBugImage
struct as a class in my C# code as follows:

[StructLayout(LayoutKind.Sequential)]
unsafe public class LadybugImage{
public UInt32 uiCols = 0;
public UInt32 uiRows = 0;
public LadybugVideoMode videoMode = new LadybugVideoMode();
public LadybugTimestamp timestamp = new LadybugTimestamp();
public LadybugImageInfo imageInfo = new LadybugImageInfo();
// public string pData = "";
unsafe public byte* pData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public UInt32[] ulReserved;
}

I suspect that the member pData is causing me grief, and/or the fact
that I used class instead of struct. Any suggestions here? If it
weren't for the complex structures, I think this would be pretty easy.

I couldn't help but notice that you substituted a 6 for LB_NUM_CAMERAS
when declaring pBuffer. Are you familiar with the LadyBug API? If so
are you using it w/ .NET?

Thanks again,
Don
"BMermuys" <so*****@someone.com> wrote in message news:<ud**************@TK2MSFTNGP09.phx.gbl>...
Hi,

You can't have a managed type that you can pass as such.

1. You can use a managed type and an unmanaged buffer and copy between them
after and/or before the function call.

* managed buffer:
byte [][] mBuffer = new byte[LB_NUM_CAMERAS][];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
mBuffer[i] = new byte[ LB_COLS * LB_ROWS * 4 ];

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* copy managed to unmanaged (eg before function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( mBuffer[i], 0, pBuffer[i], LB_COLS * LB_ROWS * 4 );

* copy unmanaged to managed (eg after function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( pBuffer[i], mBuffer[i], 0, LB_COLS * LB_ROWS * 4 );

* unmanaged function :

[DllImport(....) ]
ladybugConvertToMultipleBGRU32( ..., ... , IntPtr [] p, ... );

pBuffer is an IntPtr[] so pass it as the 3th parameter.

* cleanup unmanaged memory
for (int i= 0; i<LB_NUM_CAMERAS; ++i )
Marshal.FreeHGlobal ( pBuffer[i] );
2. _OR_ you can only use an unmanaged buffer and manipulate this with
properties or methods. This way you avoid copying. (You could put this in
a class and make sure there is access to pBuffer so you can call the
unmanaged function)

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* read data
public byte ReadData( int camera, int idx )
{
// TODO check if idx < rows*cols*4
return Marshal.ReadByte ( pBuffer[camera], idx );
}

* write data
public void WriteData( int camera, int idx, byte value )
{
// TODO check if idx < rows*cols*4
Marshal.WriteByte ( pBuffer[camera], idx, value );
}

HTH,
greetings
"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don

Nov 16 '05 #5

P: n/a
Hi,

"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
Hi,

Thanks for your reply. I am still having some trouble, probably with
the 2nd parameter (LadybugImage* pimage). I declared the LadyBugImage
struct as a class in my C# code as follows:

[StructLayout(LayoutKind.Sequential)]
unsafe public class LadybugImage{
public UInt32 uiCols = 0;
public UInt32 uiRows = 0;
public LadybugVideoMode videoMode = new LadybugVideoMode();
public LadybugTimestamp timestamp = new LadybugTimestamp();
public LadybugImageInfo imageInfo = new LadybugImageInfo();
// public string pData = "";
unsafe public byte* pData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
public UInt32[] ulReserved;
}

I suspect that the member pData is causing me grief, and/or the fact
that I used class instead of struct. Any suggestions here? If it
I can only say that if the parameter is LadybugImage* then you can use a
class or a struct as ref parameter). Both are valid.
weren't for the complex structures, I think this would be pretty easy.

I couldn't help but notice that you substituted a 6 for LB_NUM_CAMERAS
when declaring pBuffer. Are you familiar with the LadyBug API? If so
Not at all. I just read your previous post. I did check the internet, found
the ladybug but no public information about the sdk.

If you want more help you should post all c structs (concerning the
function). Also some information about what pData suppose to do. Do you
need to fill it, does the dll fill it or does the dll just set a pointer to
allocated data.
Maybe some c code that demonstrates the complete use of the function, etc...

hth,
greetings
are you using it w/ .NET?

Thanks again,
Don
"BMermuys" <so*****@someone.com> wrote in message

news:<ud**************@TK2MSFTNGP09.phx.gbl>...
Hi,

You can't have a managed type that you can pass as such.

1. You can use a managed type and an unmanaged buffer and copy between them after and/or before the function call.

* managed buffer:
byte [][] mBuffer = new byte[LB_NUM_CAMERAS][];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
mBuffer[i] = new byte[ LB_COLS * LB_ROWS * 4 ];

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* copy managed to unmanaged (eg before function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( mBuffer[i], 0, pBuffer[i], LB_COLS * LB_ROWS * 4 );

* copy unmanaged to managed (eg after function call)
for (int i=0; i<LB_NUM_CAMERAS; ++i)
Marshal.Copy ( pBuffer[i], mBuffer[i], 0, LB_COLS * LB_ROWS * 4 );

* unmanaged function :

[DllImport(....) ]
ladybugConvertToMultipleBGRU32( ..., ... , IntPtr [] p, ... );

pBuffer is an IntPtr[] so pass it as the 3th parameter.

* cleanup unmanaged memory
for (int i= 0; i<LB_NUM_CAMERAS; ++i )
Marshal.FreeHGlobal ( pBuffer[i] );
2. _OR_ you can only use an unmanaged buffer and manipulate this with
properties or methods. This way you avoid copying. (You could put this in a class and make sure there is access to pBuffer so you can call the
unmanaged function)

* unmanaged buffer:
IntPtr [] pBuffer = new IntPtr[6];
for (int i=0; i<LB_NUM_CAMERAS; ++i)
pBuffer[i] = Marshal.AllocHGlobal( LB_COLS * LB_ROWS * 4 );

* read data
public byte ReadData( int camera, int idx )
{
// TODO check if idx < rows*cols*4
return Marshal.ReadByte ( pBuffer[camera], idx );
}

* write data
public void WriteData( int camera, int idx, byte value )
{
// TODO check if idx < rows*cols*4
Marshal.WriteByte ( pBuffer[camera], idx, value );
}

HTH,
greetings
"Don" <ka**@wsdot.wa.gov> wrote in message
news:13**************************@posting.google.c om...
I have a third party C++ DLL that I am trying to use from C#. The
specific function I am trying to use is declared in C++ as follows:

ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
It is used, in C++, as follows (some code chopped for brevety):

unsigned char* arpTextureBuffers[ LADYBUG_NUM_CAMERAS ];
for(i = 0; i<LADYBUG_NUM_CAMERAS;i++)
{
arpTextureBuffers[i] =
new unsigned char[LADYBUG_RAW_IMAGE_COLS * LADYBUG_RAW_IMAGE_ROWS *
4];
}

error = ladybugConvertToMultipleBGRU32(
ladybug,
&image,
&arpTextureBuffers[0],
NULL);
I have tried (unsuccessfully, for the past two days) many combinations
of DllImport function declarations and ways of constructing the item
to pass in the third parameter (&arpTextureBuffers[0]). I have seen a
zillion posts, but none have been close enough to help me. How do I
construct the DllImport function, and how to I create the appropriate
item to pass to the third parameter? Any help would be greatly
appreciated.

Thanks in advance,
Don

Nov 16 '05 #6

P: n/a
Don
Hi again,

Thanks for the response. The relavent C++ typedefs are as follows:

typedef struct LadybugImage
{
/** Columns, in pixels, of a single image corresponding to the
current
video mode. */
unsigned int uiCols;
/** Rows, in pixels, of a single image corresponding to the current
video mode. */
unsigned int uiRows;
/** Video mode that this image was captured with. */
LadybugVideoMode videoMode;
/** Timestamp of this image. */
LadybugTimestamp timeStamp;
/** Image information for this image. */
LadybugImageInfo imageInfo;
/**
* Pointer to the actual image data. The data will be of length
* iRows * iCols * LADYBUG_NUM_CAMERAS. The format of this data
* is byte interleaved by camera and not useful for anything
besides
* feeding into one of the colour processing functions, or storage
* on disk for later processing.
*/
unsigned char* pData;
/** Reserved for future image information */
unsigned long ulReserved[ 4 ];

} LadybugImage;

/**
* The possible ladybug preview video modes. Modes other than
1024x768 do
* hardware downsampling to provide higher framerates. These do not
affect
* the size of the images saved to the HD.
*/
typedef enum LadybugVideoMode
{
/** 1024 x 768 x 6 cameras */
LADYBUG_VIDEOMODE_LADYBUG_1024x768x6,
/** 512 x 384 x 6 cameras */
LADYBUG_VIDEOMODE_LADYBUG_512x384x6,
/** 256 x 192 x 6 cameras */
LADYBUG_VIDEOMODE_LADYBUG_256x192x6,
/** 128 x 96 x 6 cameras */
LADYBUG_VIDEOMODE_LADYBUG_128x96x6,
/** Number of possible video modes. */
LADYBUG_NUM_VIDEOMODES,
/** Hook for "any usable video mode." */
LADYBUG_VIDEOMODE_ANY,

} LadybugVideoMode;

/**
* The timestamp structure for ladybug images. "Cycle time" in this
context
* is a low-level 1394 construct used for synchronizing cameras across
* multiple nodes.
*/
typedef struct LadybugTimestamp
{
/** The number of seconds since the epoch. */
unsigned long ulSeconds;
/** The microseconds component. */
unsigned long ulMicroSeconds;
/** The cycle time seconds. 0-127. */
unsigned long ulCycleSeconds;
/** The cycle time count. 0-7999. */
unsigned long ulCycleCount;

} LadybugTimestamp;

/**
* Out of band image information stored to the hard drive as part of
each
* image set at capture time.
*/
typedef struct LadybugImageInfo
{
/** Constant fingerprint, should be 0xCAFEBABE */
unsigned long ulFingerprint;
/** Structure version number, should be 0x00000002 */
unsigned long ulVersion;
/** Timestamp, in seconds, since the UNIX time epoch. */
unsigned long ulTimeSeconds;
/** Microsecond fraction of above second */
unsigned long ulTimeMicroSeconds;
/** Sequence number of the image. Reset to zero when the head
powers up
* and incremented for every image. */
unsigned long ulSequenceId;
/** Horizontal refresh rate. (reserved) */
unsigned long ulHRate;
/** Actual adjusted gains used by each of the 6 cameras. Similar
to the
* DCAM gain register. */
unsigned long arulGainAdjust[ 6 ];
/** A copy of the DCAM whitebalance register */
unsigned long ulWhiteBalance;
/** This is the same as register 0x1044, described in the PGR
Dragonfly
* Technical Reference Manual. */
unsigned long ulBayerGain;
/** This is the same as register 0x1040, described in the PGR
Dragonfly
* Technical Reference Manual. */
unsigned long ulBayerMap;
/** A copy of the Brightness DCAM register. */
unsigned long ulBrightness;
/** A copy of the Gamma DCAM register. */
unsigned long ulGamma;
/** The head unit serial number. */
unsigned long ulSerialNum;
/** Shutter values for each camera. Similar to the DCAM shutter
* register. */
unsigned long ulShutter[ 6 ];
/** Reserved for future out of band image values. */
unsigned long ulReserved[ 6 ];

} LadybugImageInfo;
The function I need to call follows:

/**
* Parse the 6 images in a LADYBUG_VIDEOMODE_LADYBUG LadybugImage into
* 6 BGRU32 buffers. Color processing will use the current color
processing
* method.
*
* @param context The LadybugContext to access.
* @param arpszDestBuffers An array of pointers to destination
buffers that
* will hold the processed images.
* @retval pImageInfo Image information extracted from the
retrieved
* image. Use NULL to disable.
*
* @return A LadybugError indicating the success of the function.
*
* @note BGRU32 images will only be produced for the camera units that
* are included in the processing camera bit mask
* (see ladybugSetProcessingCameras()).
* @note The alpha mask (see ladybuggeom.h) will only be written to
the
* destination buffer the first time any of the Convert
functions
* are called. If you wish to use a different destination
buffer,
* call ladybugSetAlphaMasking( true ) again.
*/
LADYBUGDLL_API LadybugError
ladybugConvertToMultipleBGRU32(
LadybugContext context,
const LadybugImage* pimage,
unsigned char* arpszDestBuffers[ LADYBUG_NUM_CAMERAS ],
LadybugImageInfo* pImageInfo );
Don't worry about LadybugContext. I am able to succesfully create and
destroy it via two other API calls. I feel pretty good about the
code you supplied for creating and copying back & forth to the
unmanaged buffer. I am thinking the way I declared the LadybugImage
struct is my problem (particularily the pData member). Any
suggestions would be greatly appreciated. Let me know if you need
more info.

Thanks again,
Don
Nov 16 '05 #7

P: n/a
Hi,

c# structs:

[StructLayout(LayoutKind.Sequential)]
public struct LadyBugTimestamp
{
uint Seconds;
uint MicroSeconds;
uint CycleSeconds;
uint CycleCount;
}

public enum LadybugVideoMode
{
LADYBUG_VIDEOMODE_LADYBUG_1024x768x6,
LADYBUG_VIDEOMODE_LADYBUG_512x384x6,
LADYBUG_VIDEOMODE_LADYBUG_256x192x6,
LADYBUG_VIDEOMODE_LADYBUG_128x96x6,
LADYBUG_NUM_VIDEOMODES,
LADYBUG_VIDEOMODE_ANY
}

[StructLayout(LayoutKind.Sequential)]
public struct LadybugImageInfo
{
public uint Fingerprint;
public uint Version;
public uint TimeSeconds;
public uint TimeMicroSeconds;
public uint SequenceId;
public uint HRate;

[MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
public uint[] GainAdjust;

public uint WhiteBalance;
public uint BayerGain;
public uint BayerMap;
public uint Brightness;
public uint Gamma;
public uint SerialNum;

[MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
public uint[] Shutter;

[MarshalAs(UnmanagedType.ByValArray,SizeConst=6)]
public uint[] Reserverd;

public LadybugImageInfo(int unused)
{ // constructor
GainAdjust = new byte[6];
Shutter = new byte[6];
Reserverd = new byte[6];
}
}

[StructLayout(StructLayoutEnum.Sequential)]
public struct LadybugImage
{
public uint Cols;
public uint Rows;
public int videoMode; // cast VideModeEnums to int or parse from int
public LadybugTimeStamp timeStamp;
public LadybugImageInfo imageInfo;
public IntPtr pData;

[MarshalAs(UnmanagedType.ByValArray,SizeConst=4)]
public uint[] Reserved;

public LadybugImage(int unused)
{ // constructor
timeStamp = new LadybugTimeStamp();
imageInfo = new LadybugImageInfo(0);
Reserverd = new byte[4];
}
}

[DllImport(...)]
public static extern int ladybugConvertToMultipleBGRU32(
LadybugContext context,
ref LadybugImage image,
IntPtr[] pDestBuffers,
ref LadybugImageInfo ImageInfo );

public void test()
{
LadybugImagInfo ImageInfo = new LadybugImageInfo(0);

LadybugImage Image = new LadybugImage(0); // (*)
// eg. GetImage ( ref Image );

// Allocate unmanaged memory for DestBuffers
IntPtr[] pDestBuffers = new IntPtr[6];
for (int i=0; i<6; ++i)
pDestBuffers[i] = Marshal.AllocHGlobal(rows*cols*4);

// Call unmanaged function
ladybugConvertToMultipleBGRU32( context, ref Image, pDestBuffers, ref
ImageInfo );

// Create managed buffer, copy pDestBuffers into it and cleanup
unmanaged buffer
byte [][] DestBuffers = new byte[6][];
for (int i=0; i<6; ++i)
{
DestBuffers[i] = new byte[rows*cols*4];
Marshal.Copy( pDestBuffers[i], DestBuffers[i], 0, rows*cols*4 );
Marshal.HFreeGlobal( pDestBuffers[i] );
}

// If you allocated memory for Image.pImage then cleanup
Marshal.HFreeGlobal( Image.pImage );

// result is in DestBuffers
}

You may want to rearrange it.

(*)
It's still not clear where the data comes from that you want in Image.pData
:

1. If you have a unmanaged function (eg. void GetImage (LadybugImage*
image) ) which fills an Image structure then there are 2 options:
a. the function allocates memory for pData, then you don't have to
allocate memory yourself and the dll should export a function that frees the
data it allocated (eg. FreeImage(...) )
b. the caller must allocate memory for pData before calling GetImage,
then you need to allocate memory yourself:
Image.pData = Marshal.AllocHGlobal( Image.Rows * Image.Cols * 6 );

2. If the imagedata comes from a managed type, you'll need to allocate
memory and use Marshal.Copy or Marshal.WriteByte to marshal the data.

If you don't want to use parameter ImageInfo* then you can declare it as an
IntPtr and pass IntPtr.Zero.

HTH,
Greetings

Nov 16 '05 #8

P: n/a
Don
Hi again

It turns out the creators of the Ladybug API have built in a versioning scheme using macros in the C++ environment. They apparently did not build the API to be used from outside of C++. The method names are transformed during the compile process. I was calling a method called ladybugConvertToMultipleBGRU32, based on the documentation and what I found in the .h file. However, in the compiled dll that I am using, the method I want is ladybugConvertToMultipleBGRU32_1_1_1_1_1_1_2_2. Their versioning scheme accounts for changes to structs that are passed as parameters. Somehow (I don't fully understand it), when I made my call to the ladybugConvertToMultipleBGRU32 method, the API was able to tell that I was trying to call the original version of the method and that there is a newer version that I should be using instead. This resulted in a message box (probably a Win API call, since I didn't have any messagebox code) telling me that I am trying to use an old version and should recompile with a newer version

I just wanted to thank you for all of your help. The advice you gave for parameter #3 (IntPtr[] arpszDestBuffers): type to use; and allocating/copying between managed/unmanaged helped alot

Thanks again
Don
Nov 16 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.