Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 643
  • Last Modified:

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 0x01FWIA / 0x02FSTI */
    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.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?
0
ttnetworks
Asked:
ttnetworks
  • 2
  • 2
1 Solution
 
AlexFMCommented:
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.
0
 
ttnetworksAuthor Commented:
Hi,

This work needs to be completed in C#...
0
 
AlexFMCommented:
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(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.
0
 
ttnetworksAuthor Commented:
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));
            else
            {
                Console.WriteLine("The buffer size is " + bufferSize);

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

            Marshal.FreeHGlobal(pDeviceInfo);



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);
      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->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 );
      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);
      }
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now