ttnetworks
asked on
C++ SDK Access from C#
I'm trying to call a C++ function in an SDK from a C# app.
The function is defined as:
prCAPI PR_GetDeviceList(
prUInt32* pBufferSize,
prDeviceList* pDeviceList
);
where pBufferSize is a pointer to the buffer size and pDeviceList is a pointer to a prDeviceList struct.
prCAPI is an UInt32 and is 0x00 if the function is successful.
The structs are defined in a header file as the following:
typedef struct{
prWChar DeviceInternalName[512]; /* Internal device name (512 characters) */
prWChar ModelName[32]; /* Camera model name (32 characters) */
prUInt16 Generation; /* Camera generation number */
prUInt32 Reserved1; /* Reserved */
prUInt32 ModelID; /* Camera model ID */
prUInt16 Reserved2; /* Reserved */
prPorttype PortType; /* Port type 0x01FWIA / 0x02FSTI */
prUInt32 Reserved3; /* Reserved */
}prDeviceInfoTable;
typedef struct{
prUInt32 NumList; /* Number of camera device information included in this structure */
prDeviceInfoTable DeviceInfo[prANY]; /* Camera device information. This array is variable */
}prDeviceList;
The types are defined as:
unsigned long prCAPI
unsigned ushort prWChar
usigned long prUInt32
unsigned short prUInt16
unsigned short prPorttype
prAny 1
Using InteropServices in C#, I re wrote the function and the structs:
public static extern UInt32 PR_GetDeviceList(ref UInt32 pBufferSize, out IntPtr pDeviceList);
public struct prDeviceList
{
public UInt32 NumList; /* Number of camera device information included in the struct */
public prDeviceInfoTable[] DeviceInfo; /* Camera device information */
}
[StructLayout(LayoutKind.S equential, CharSet=CharSet.Unicode)]
public struct prDeviceInfoTable
{
[MarshalAs(UnmanagedType.B yValTStr, SizeConst=512)]
public string DeviceInternalName; /* Internal device name (512 characters) */
[MarshalAs(UnmanagedType.B yValTStr, SizeConst = 32)]
public string ModelName; /* Camera model name (32 characters) */
public UInt16 Generation; /* Camera generation number */
public UInt32 Reserved1; /* Reserved */
public UInt32 ModelID; /* Camera model ID */
public UInt16 Reserved2; /* Reserved */
public UInt16 PortType; /* Port type 0x01FWIA / 0x02FSTI */
public UInt32 Reserved3; /* Reserved */
}
Can anyone tell me how i go about calling the function then retrieve the prDeviceList struct using the pointer and then enumerate the prDeviceInfoTable structs in the array prDeviceList.DeviceInfo?
The function is defined as:
prCAPI PR_GetDeviceList(
prUInt32* pBufferSize,
prDeviceList* pDeviceList
);
where pBufferSize is a pointer to the buffer size and pDeviceList is a pointer to a prDeviceList struct.
prCAPI is an UInt32 and is 0x00 if the function is successful.
The structs are defined in a header file as the following:
typedef struct{
prWChar DeviceInternalName[512]; /* Internal device name (512 characters) */
prWChar ModelName[32]; /* Camera model name (32 characters) */
prUInt16 Generation; /* Camera generation number */
prUInt32 Reserved1; /* Reserved */
prUInt32 ModelID; /* Camera model ID */
prUInt16 Reserved2; /* Reserved */
prPorttype PortType; /* Port type 0x01FWIA / 0x02FSTI */
prUInt32 Reserved3; /* Reserved */
}prDeviceInfoTable;
typedef struct{
prUInt32 NumList; /* Number of camera device information included in this structure */
prDeviceInfoTable DeviceInfo[prANY]; /* Camera device information. This array is variable */
}prDeviceList;
The types are defined as:
unsigned long prCAPI
unsigned ushort prWChar
usigned long prUInt32
unsigned short prUInt16
unsigned short prPorttype
prAny 1
Using InteropServices in C#, I re wrote the function and the structs:
public static extern UInt32 PR_GetDeviceList(ref UInt32 pBufferSize, out IntPtr pDeviceList);
public struct prDeviceList
{
public UInt32 NumList; /* Number of camera device information included in the struct */
public prDeviceInfoTable[] DeviceInfo; /* Camera device information */
}
[StructLayout(LayoutKind.S
public struct prDeviceInfoTable
{
[MarshalAs(UnmanagedType.B
public string DeviceInternalName; /* Internal device name (512 characters) */
[MarshalAs(UnmanagedType.B
public string ModelName; /* Camera model name (32 characters) */
public UInt16 Generation; /* Camera generation number */
public UInt32 Reserved1; /* Reserved */
public UInt32 ModelID; /* Camera model ID */
public UInt16 Reserved2; /* Reserved */
public UInt16 PortType; /* Port type 0x01FWIA / 0x02FSTI */
public UInt32 Reserved3; /* Reserved */
}
Can anyone tell me how i go about calling the function then retrieve the prDeviceList struct using the pointer and then enumerate the prDeviceInfoTable structs in the array prDeviceList.DeviceInfo?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Do you have C++ code sample for this? Or description of function algorithm?
prCAPI PR_GetDeviceList(
prUInt32* pBufferSize,
prDeviceList* pDeviceList);
Assuming that pBufferSize points to single Int32 value, and pDeviceList points to single DeviceList structure, function declaration should be:
public static extern UInt32 PR_GetDeviceList(ref UInt32 pBufferSize, ref prDeviceList);
Pass int and prDeviceList this bunction by reference.
The trick is to define prDeviceList structure:
typedef struct{
prUInt32 NumList; /* Number of camera device information included in this structure */
prDeviceInfoTable DeviceInfo[prANY]; /* Camera device information. This array is variable */
}prDeviceList;
NumList should be defined as int or Int32 ot UInt32 - doesn't matter.
prDeviceInfoTable should be defined as IntPtr. Allocate unmanaged memory block for it using Marshal.AllocHGlobal. Allocation size should be Marshal.SizeOf(prDeviceInf oTable) * n, n is number of structures. To fill this unmanaged clock you need Marshal.StructureToPtr Method. Make this n times incrementing IntPtr handle to Marshal.SizeOf(prDeviceInf oTable) bytes.
prCAPI PR_GetDeviceList(
prUInt32* pBufferSize,
prDeviceList* pDeviceList);
Assuming that pBufferSize points to single Int32 value, and pDeviceList points to single DeviceList structure, function declaration should be:
public static extern UInt32 PR_GetDeviceList(ref UInt32 pBufferSize, ref prDeviceList);
Pass int and prDeviceList this bunction by reference.
The trick is to define prDeviceList structure:
typedef struct{
prUInt32 NumList; /* Number of camera device information included in this structure */
prDeviceInfoTable DeviceInfo[prANY]; /* Camera device information. This array is variable */
}prDeviceList;
NumList should be defined as int or Int32 ot UInt32 - doesn't matter.
prDeviceInfoTable should be defined as IntPtr. Allocate unmanaged memory block for it using Marshal.AllocHGlobal. Allocation size should be Marshal.SizeOf(prDeviceInf
ASKER
I made the suggested changes to the function and the prDeviceList struct and was able to execute the function successfully, but when i tried to marshal the pointer into a prDeviceInfoTable struct using Marshal.StructureToPtr, my program just exited at that point without throwing any exception. Here's my code:
//Allocate enough memory for n devices
int n = 5;
IntPtr pDeviceInfo = Marshal.AllocHGlobal(Marsh al.SizeOf( typeof(prT ype.prDevi ceInfoTabl e)) * n);
UInt32 bufferSize = (UInt32)(Marshal.SizeOf(ty peof(prTyp e.prDevice List)) + (Marshal.SizeOf(typeof(prT ype.prDevi ceInfoTabl e)) * n));
prType.prDeviceList DeviceList = new prType.prDeviceList();
DeviceList.pDeviceInfo = pDeviceInfo;
err = PsRecApi.PR_GetDeviceList( ref bufferSize, ref DeviceList);
if (err != prError.prOK)
Console.WriteLine("Error: 0x" + string.Format("{0:x0}", err));
else
{
Console.WriteLine("The buffer size is " + bufferSize);
prType.prDeviceInfoTable info = new prType.prDeviceInfoTable() ;
Marshal.StructureToPtr(inf o, DeviceList.pDeviceInfo, false);
}
Marshal.FreeHGlobal(pDevic eInfo);
The SDK in question is the Canon Remote Capture SDK (PS-RecSDK). Here's some of their sample code:
prResponse err = prOK;
prUInt32 count = 0L;
prUInt32 index;
prUInt32 BufferSize = 0L;
prDeviceList* pGetDevList = NULL;
/* Allocate memory 10 devices */
BufferSize = (prUInt32)sizeof(prDeviceL ist) + (prUInt32)(sizeof(prDevice InfoTable) * 9L);
for(;;)
{
pGetDevList = (prDeviceList*)new prUInt8[BufferSize];
/* Enumerate camera devices by PS-ReC SDK */
err = PR_GetDeviceList( &BufferSize, (prDeviceList*)pGetDevList );
if(!err)
{
break;
}
if((err & prERROR_ERRORID_MASK) != prINSUFFICIENT_BUFFER)
{
goto ErrHandler;
}
/* If error is prINSUFFICIENT_BUFFER, */
/* then change the buffer size. */
delete [] pGetDevList;
pGetDevList = NULL;
}
if(pGetDevList->NumList > 0)
{
for(index = 0; index<(pGetDevList->NumLis t); index++)
{
SDK_AND_INFO* pDeviceInfo = new SDK_AND_INFO;
char MBModelName[40];
pDeviceInfo->m_SelectedSDK = CAMERA_ENUM_PRSDK;
memcpy( &((pDeviceInfo->SrcInfo).S electedSrc _PRSDK), &(pGetDevList->DeviceInfo[ index]), sizeof(prDeviceInfoTable) );
WideCharToMultiByte(CP_ACP , 0, (pDeviceInfo->SrcInfo).Sel ectedSrc_P RSDK.Model Name, -1, MBModelName, 40-1, 0, 0);
m_CameraList.InsertString( index, (const char *)MBModelName);
m_CameraList.SetItemDataPt r( index, pDeviceInfo );
}
}
/* Enumerate camera devices by CD-SDK */
err = (prResponse)Enum_CDSDK( (cdUInt32*)&count, (cdUInt32)pGetDevList->Num List );
if(err)
{
goto ErrHandler;
}
if((pGetDevList->NumList == 0) && (count == 0))
{
m_CameraList.InsertString( 0, "(None)" );
}
m_CameraList.SetCurSel( 0 );
ErrHandler:
if(pGetDevList)
delete [] pGetDevList;
if(err)
{
char szErrStr[256];
wsprintf( szErrStr, "ErrorCode = 0x%08X", err );
MessageBox( szErrStr );
EndDialog(0);
}
//Allocate enough memory for n devices
int n = 5;
IntPtr pDeviceInfo = Marshal.AllocHGlobal(Marsh
UInt32 bufferSize = (UInt32)(Marshal.SizeOf(ty
prType.prDeviceList DeviceList = new prType.prDeviceList();
DeviceList.pDeviceInfo = pDeviceInfo;
err = PsRecApi.PR_GetDeviceList(
if (err != prError.prOK)
Console.WriteLine("Error: 0x" + string.Format("{0:x0}", err));
else
{
Console.WriteLine("The buffer size is " + bufferSize);
prType.prDeviceInfoTable info = new prType.prDeviceInfoTable()
Marshal.StructureToPtr(inf
}
Marshal.FreeHGlobal(pDevic
The SDK in question is the Canon Remote Capture SDK (PS-RecSDK). Here's some of their sample code:
prResponse err = prOK;
prUInt32 count = 0L;
prUInt32 index;
prUInt32 BufferSize = 0L;
prDeviceList* pGetDevList = NULL;
/* Allocate memory 10 devices */
BufferSize = (prUInt32)sizeof(prDeviceL
for(;;)
{
pGetDevList = (prDeviceList*)new prUInt8[BufferSize];
/* Enumerate camera devices by PS-ReC SDK */
err = PR_GetDeviceList( &BufferSize, (prDeviceList*)pGetDevList
if(!err)
{
break;
}
if((err & prERROR_ERRORID_MASK) != prINSUFFICIENT_BUFFER)
{
goto ErrHandler;
}
/* If error is prINSUFFICIENT_BUFFER, */
/* then change the buffer size. */
delete [] pGetDevList;
pGetDevList = NULL;
}
if(pGetDevList->NumList > 0)
{
for(index = 0; index<(pGetDevList->NumLis
{
SDK_AND_INFO* pDeviceInfo = new SDK_AND_INFO;
char MBModelName[40];
pDeviceInfo->m_SelectedSDK
memcpy( &((pDeviceInfo->SrcInfo).S
WideCharToMultiByte(CP_ACP
m_CameraList.InsertString(
m_CameraList.SetItemDataPt
}
}
/* Enumerate camera devices by CD-SDK */
err = (prResponse)Enum_CDSDK( (cdUInt32*)&count, (cdUInt32)pGetDevList->Num
if(err)
{
goto ErrHandler;
}
if((pGetDevList->NumList == 0) && (count == 0))
{
m_CameraList.InsertString(
}
m_CameraList.SetCurSel( 0 );
ErrHandler:
if(pGetDevList)
delete [] pGetDevList;
if(err)
{
char szErrStr[256];
wsprintf( szErrStr, "ErrorCode = 0x%08X", err );
MessageBox( szErrStr );
EndDialog(0);
}
ASKER
This work needs to be completed in C#...