2014-12-12 3 views
0

мне нужно использовать C# для управления тестовым модуля с ++ DLL C и ниже структура и функция инициализации первоначально определен в C++ файла заголовкапередавая структуру при вызове C++ функции DLL в C#

typedef unsigned char  uint8_t; 
typedef unsigned long  uint32_t; 
typedef unsigned short  uint16_t; 
typedef unsigned char  bool_t; 
typedef signed short  int16_t; 
typedef signed char   int8_t; 
typedef signed long   int32_t; 

#define ER  0x2 
#define BS  0x4000 

typedef enum { 
    nI2C, 
    nSPI, 
    nUSB, 
    nSDIO 
} mBus; 

typedef uint8_t cAddr; 

typedef enum { 
    nCPHA0=0, 
    nCPHA1 
} mPhase; 

typedef enum { 
    nCPOL0=0, 
    nCPOL1 
} mSpiPol; 

typedef struct { 
    mPhase cPha; 
    mSpiPol cPol; 
} mSpiCfg; 

typedef struct { 
    uint8_t    xo; 
    bool_t    init_bus_only;       
    uint32_t   zone; 
    mBus    bustype; 
    mBus    transporttype; 
    cAddr   i2cAddr; 
    mSpiCfg   spiCfg; 
    bool_t    use_pmu; 
} mInitCfg; 

typedef enum { 
    OK = 0, 
    FAIL = -1, 
    BUS_ALREADY_LOADED = -2, 
    BUS_TYPE_UNKNOWN = -3, 
    BUS_LOAD_LIBRARY_FAIL = -4, 
    BUS_GET_PROC_FAIL = -5, 
    BUS_INIT_FAIL = -6, 
    Err_CHIP_INIT = -7 
} retCode; 

typedef struct { 
    mInitCfg cfg; 
} mDrvIn; 

__declspec(dllexport) retCode cp_init(mDrvIn * inp); 

В C++ , это называется как ниже

static void init(void) 
{ 
mDrvIn di; 
retCode rc; 

memset(&di, 0, sizeof(mDrvIn)); 

di.cfg.bustype = nI2C; 
di.cfg.init_bus_only = 1; 
di.cfg.transporttype = di.cfg.bustype; 
di.cfg.zone = ER | BS; 

    rc = cp_init(&di); 
    if(rc < 0) { 
    printf("Failed to initialize. Error code %d: %s", rc, to_string(rc)); 
    return; 
} 
} 

и я использую ниже структур C# при вызове функции DLL

using cAddr = System.Byte; 
public enum mBus 
{ 
    nI2C, 
    nSPI, 
    nUSB, 
    nSDIO 
}; 

public enum mPhase 
{ 
    nCPHA0 = 0, 
    nCPHA1 
}; 

public enum mSpiPol 
{ 
    nCPOL0 = 0, 
    nCPOL1 
}; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct mSpiCfg 
{ 
    public mPhase cPha; 
    public mSpiPol cPol; 
}; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct mInitCfg 
{ 
    public byte xo; 
    public byte init_bus_only; 
    public uint zone; 
    public mBus bustype; 
    public mBus transporttype; 
    public cAddr i2cAddr; 
    public mSpiCfg spiCfg; 
    public byte use_pmu; 
}; 

public enum retCode 
{ 
    OK = 0, 
    FAIL = -1, 
    BUS_ALREADY_LOADED = -2, 
    BUS_TYPE_UNKNOWN = -3, 
    BUS_LOAD_LIBRARY_FAIL = -4, 
    BUS_GET_PROC_FAIL = -5, 
    BUS_INIT_FAIL = -6, 
    Err_CHIP_INIT = -7 
}; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct mDrvIn 
{ 
    public mInitCfg cfg; 
}; 

[DllImport("mdrv.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] 
public static extern retCode cp_init(ref mDrvIn inp); 

Я использовал ниже код для инициализации

public static void init() 
{ 
    mDrvIn di = new mDrvIn(); 
    retCode rc = new retCode(); 

    di.cfg.bustype = mBus.nI2C; 
    di.cfg.init_bus_only = 1; 
    di.cfg.transporttype = di.cfg.bustype; 
    di.cfg.zone = 0x2 | 0x4000; 

    rc = cp_init(ref di); 
    if (rc < 0) 
    { 
     Console.Write("Failed to initialize. Error code: " + rc); 
     return; 
    } 
} 

Проблема заключается в том, что с помощью C++, чтобы инициализировать модуль работает нормально, но C# не было бы всегда возвращать код ошибки -5 (что означает ошибку шины: не удалось перечислить шины функция внутри DLL), указатель на структуру, кажется, передается в DLL без ошибок, поэтому мне было интересно, есть ли что-то неправильное в структурах, которые я преобразовал в C#, поэтому аргумент, переданный функции C++, поврежден или что-то еще, может кто-нибудь мне поможет? заранее спасибо.

+0

Проверьте 'Marshal.SizeOf()' ваших типов C# и сравните 'sizeof()' ваших типов C++. – flyx

+0

printf ("size =>% d", di) это дает мне 256 Marshal.SizeOf (di) дает мне 32 , но не знаю, какая разница? моя структура C# по-прежнему неправильна даже после изменения int в байт для bool_t? – Allen

+0

Нет разницы, 'sizeof' возвращает биты и' Marshal.SizeOf' байты, поэтому они одинаковы. – flyx

ответ

0

В коде C++, вы определяете bool_t в качестве unsigned char (8 бит), но в коде C#, вы используете int (32 бита), так что ваша структура перестать быть действительной после init_bus_only.

Редактировать: Кроме того, в вашем коде на C++ вы устанавливаете init_bus_only в 1, а в коде C# вы этого не делаете, но вы должны найти это без помощи. Дважды проверьте свой код, прежде чем спрашивать.

+0

Спасибо, я поменял их на байты, как показано ниже public byte init_bus_only; открытый байт use_pmu; , но теперь я получаю BUS_LOAD_LIBRARY_FAIL, но не могу понять, что еще не так? – Allen

+0

Если ничего очевидного не так, проверьте, что вызывает 'BUS_LOAD_LIBRARY_FAIL' в документации DLL. – flyx

+0

Извините, что я знаю об init_bus_only, на самом деле я немного изменил имена переменных и забыл изменить его при публикации, я установил инициализирующие элементы и значения точно так же, как и образец C++, все еще пытаясь найти, что привело к сбою структуры C#. – Allen

Смежные вопросы