开发者

How does one create structures for C# originally written in C++

开发者 https://www.devze.com 2023-01-29 05:16 出处:网络
I am working on an embedded ARM platform and wish to have control over some of the GPIO pins.I\'ve experience in C and am a newcomer to C#.It seems that controlling low-level hardware is difficult fro

I am working on an embedded ARM platform and wish to have control over some of the GPIO pins. I've experience in C and am a newcomer to C#. It seems that controlling low-level hardware is difficult from managed-code applications. I have Windows CE6.0 and .NET Compact Framework 2 running on my hardware.

I've found an example, written in C++ that would allow me access to GPIO port pins, however, I am struggling to implement the example in C#.

The following snippet shows how DeviceIOcontrol is used to control port pins:

    const struct pio_desc hw_pio[] =
    {
        {"LED1", AT91C_PIN_PA(13), 0, PIO_DEFAULT, PIO_OUTPUT},
        {"LED2", AT91C_PIN_PA(14), 0, PIO_DEFAULT, PIO_OUTPUT},
    };
    T_GPIOIOCTL_STATE * pSetState;
    T_GPIOIOCTL_STATE * pGetState;

    // Configure PIOs
    bSuccessDevIOC = DeviceIoControl(hGPIO, IOCTL_GPIO_CONFIGURE, (LPBYTE*)hw_pio, sizeof(hw_pio), NULL, 0, NULL, NULL);

Other definitions:

struct pio_desc
{
    const char *pin_name;   /* Pin Name */
    unsigned int pin_num;   /* Pin number */
    uns开发者_开发技巧igned int dft_value; /* Default value for outputs */
    unsigned char attribute;
    enum pio_type type;
};

/* I/O type */
enum  pio_type
{
    PIO_PERIPH_A,
    PIO_PERIPH_B,
    PIO_INPUT,
    PIO_OUTPUT,
    PIO_UNDEFINED
};

/* I/O attributes */
#define PIO_DEFAULT   (0 << 0)
#define PIO_PULLUP    (1 << 0)
#define PIO_DEGLITCH  (1 << 1)
#define PIO_OPENDRAIN (1 << 2)

The following is the C# definition of DeviceIOControl. The problem parameter is lpInBuffer.

[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
    internal static extern bool DeviceIoControlCE(int hDevice,
                                                 int dwIoControlCode,
                                                 byte[] lpInBuffer,
                                                 int nInBufferSize,
                                                 byte[] lpOutBuffer,
                                                 int nOutBufferSize,
                                                 ref int lpBytesReturned,
                                                 IntPtr lpOverlapped);

The questions:

How does one create these equivalent structures in C#? How does one pass these as a byte array (byte[] lpInBuffer) to the DeviceIOControl function?

Any assistance appreciated!


Use some interop decoration, for instance, a structure like following:

typedef struct 
{
    char Data[MAXCHARS];//assuming a #define MAXCHARS 15
    int Values[MAXCHARS];
} StSomeData;

would look like following in C#:

[StructLayout(LayoutKind.Sequential)]
private struct StSomeData
{
    [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 15)]
    public string Data;

   [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] Values;
}

And use it like: StSomeData[] array = new StSomeData[3];

Note that you can use IntPtr when dealing with pointers.

For instance your call to:

DeviceIoControl(hGPIO, IOCTL_GPIO_CONFIGURE, (LPBYTE*)hw_pio
               , sizeof(hw_pio), NULL, 0, NULL, NULL);

may look something like following:

IntPtr ipByte;
Marshal.StructureToPtr(StLPByte, ipByte,false);

IntPtr ipConfig;
Marshal.StructureToPtr(StIOCTL_GPIO_CONFIGURE, ipConfig, false);

IntPtr iphGPIO;
Marshal.StructureToPtr(SthGPIO, iphGPIO, false);


bool bSuccessDevIOC = DeviceIoControl(iphGPIO
                                        , ipConfig
                                        , ipByte
                                        , Marshal.SizeOf(typeof(StLPByte))
                                        , IntPtr.Zero
                                        , IntPtr.Zero
                                        , IntPtr.Zero
                                        , IntPtr.Zero);

Also, you can look into the usage of unsafe keyword and try put your code within unsafe blocks; this may be a dirty solution since this code wont be a managed code.


a byte[] is converted to LPBYTE automatically
a char* in c# is equivalent to unsigned short* in c++
a byte* in c# is a unsigned char* in c++
c#-enums behave similar enough to c++ enums. you may just write it

one important thing:
[StructLayout(LayoutKind.Sequential,Pack=1)]

0

精彩评论

暂无评论...
验证码 换一张
取 消