C++ SDK Access from C#

Posted on 2006-05-23
Last Modified: 2010-05-18
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 0x01FWIA / 0x02FSTI */
    prUInt32 Reserved3; /* Reserved */

typedef struct{
    prUInt32 NumList; /* Number of camera device information included in this structure */
    prDeviceInfoTable DeviceInfo[prANY]; /* Camera device information. This array is variable */

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.Sequential, CharSet=CharSet.Unicode)]
public struct prDeviceInfoTable
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=512)]
    public string DeviceInternalName; /* Internal device name (512 characters) */

    [MarshalAs(UnmanagedType.ByValTStr, 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 0x01FWIA / 0x02FSTI */
    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?
Question by:ttnetworks
    LVL 48

    Accepted Solution

    Before starting this work in C#, consider to do this in C++/CLI. It allows to call unmanaged code directly without PInvoke, this simplifies such calls.
    If you want ot do this in C#, I will look at this later.

    Author Comment


    This work needs to be completed in C#...
    LVL 48

    Expert Comment

    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 */

    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(prDeviceInfoTable) * 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(prDeviceInfoTable) bytes.

    Author Comment

    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(Marshal.SizeOf(typeof(prType.prDeviceInfoTable)) * n);
                UInt32 bufferSize = (UInt32)(Marshal.SizeOf(typeof(prType.prDeviceList)) + (Marshal.SizeOf(typeof(prType.prDeviceInfoTable)) * 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));
                    Console.WriteLine("The buffer size is " + bufferSize);

                    prType.prDeviceInfoTable info = new prType.prDeviceInfoTable();
                    Marshal.StructureToPtr(info, DeviceList.pDeviceInfo, false);


    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(prDeviceList) + (prUInt32)(sizeof(prDeviceInfoTable) * 9L);
                pGetDevList = (prDeviceList*)new prUInt8[BufferSize];
                /* Enumerate camera devices by PS-ReC SDK */
                err = PR_GetDeviceList( &BufferSize, (prDeviceList*)pGetDevList );
                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->NumList); index++)
                      SDK_AND_INFO* pDeviceInfo = new SDK_AND_INFO;
                      char MBModelName[40];
                      pDeviceInfo->m_SelectedSDK = CAMERA_ENUM_PRSDK;
                      memcpy( &((pDeviceInfo->SrcInfo).SelectedSrc_PRSDK), &(pGetDevList->DeviceInfo[index]), sizeof(prDeviceInfoTable) );
                      WideCharToMultiByte(CP_ACP, 0, (pDeviceInfo->SrcInfo).SelectedSrc_PRSDK.ModelName, -1, MBModelName, 40-1, 0, 0);
                      m_CameraList.InsertString(index, (const char *)MBModelName);
                      m_CameraList.SetItemDataPtr( index, pDeviceInfo );

          /* Enumerate camera devices by CD-SDK */
          err = (prResponse)Enum_CDSDK( (cdUInt32*)&count, (cdUInt32)pGetDevList->NumList );
                goto ErrHandler;

          if((pGetDevList->NumList == 0) && (count == 0))
                m_CameraList.InsertString( 0, "(None)" );

          m_CameraList.SetCurSel( 0 );


            delete [] pGetDevList;

                char      szErrStr[256];
                wsprintf( szErrStr, "ErrorCode = 0x%08X", err );
                MessageBox( szErrStr );


    Featured Post

    How to run any project with ease

    Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
    - Combine task lists, docs, spreadsheets, and chat in one
    - View and edit from mobile/offline
    - Cut down on emails

    Join & Write a Comment

    Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
    Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
    It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
    how to add IIS SMTP to handle application/Scanner relays into office 365.

    745 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    16 Experts available now in Live!

    Get 1:1 Help Now