C#封送来自C ++ DLL的无符号字符返回值

时间:2018-01-14 22:39:38

标签: c# c++ marshalling dllimport unsigned-char

我将函数从C ++ DLL导入C#应用程序。我能够导入和一些功能,但不能导入其他功能。 C ++ DLL附带了一个C ++项目,该项目展示了如何从C ++中使用它。我想在C#中复制它,但我在编组方面遇到了麻烦。这是C ++:

标头文件声明:

unsigned long __stdcall mfcs_initialisation(unsigned short serial);
unsigned long __stdcall mfcsez_initialisation(unsigned short serial);   
unsigned char __stdcall mfcs_close(unsigned long handle);
unsigned char __stdcall mfcs_set_purge_on(unsigned long int handle);
unsigned char __stdcall mfcs_set_purge_off(unsigned long int handle);

unsigned char __stdcall mfcs_get_purge(unsigned long int handle,
    unsigned char * c);

unsigned char __stdcall mfcs_get_status(
    unsigned long int handle,
    unsigned char * c);

unsigned char __stdcall mfcs_read_chan(
    unsigned long int handle,
    unsigned char canal,
    float * pressure,
    unsigned short * chrono);

unsigned char __stdcall mfcs_data_chan(
    unsigned long int  handle,
    unsigned char canal,
    unsigned char * unite,
    unsigned short * max,
    unsigned short * zero,
    unsigned short * mesure,
    unsigned short * chrono);

unsigned char __stdcall mfcs_get_serial(unsigned long int handle,
    unsigned short * us);

unsigned char __stdcall mfcs_set_auto(
    unsigned long int handle,
    unsigned char canal,
    float pcons);

unsigned char __stdcall mfcs_set_alpha(
    unsigned long int handle,
    unsigned char canal,
    unsigned char alpha);

unsigned char __stdcall mfcs_set_manual(
    unsigned long int handle,
    unsigned char canal,
    float pcons);

unsigned char __stdcall mfcs_set_zero(
    unsigned long int handle,
    unsigned char canal,
    unsigned short zero);

unsigned char __stdcall mfcs_detect(unsigned short table[256]);
unsigned char __stdcall mfcsez_detect(unsigned short table[256]);

C ++代码:

/* Define functions prototype */
typedef unsigned long(__stdcall *init)(int);
typedef unsigned char(__stdcall *purgeOn)(unsigned long handle);
typedef unsigned char(__stdcall *purgeOff)(unsigned long handle);
typedef unsigned char(__stdcall *serial)(unsigned long handle, unsigned short *serial);
typedef unsigned char(__stdcall *close)(unsigned long handle);
typedef unsigned char(__stdcall *setAuto)(unsigned long int handle, unsigned 
char canal, float pcons);
typedef unsigned char(__stdcall *readChannel)(unsigned long handle, unsigned 
char chan, float * pressure, unsigned short * chrono);
typedef unsigned char(__stdcall *setAlpha)(unsigned long int handle, unsigned 
char canal, unsigned char alpha);

int main(int argc, char *argv[])
{
/* System settings variable definition */
float start_pressure = 70;         //Pressure set (mbar) at the beginning
float target_pressure = 100;        //Maximal pressure setpoint (mbar)
unsigned char pressureChannel = 1; //Selected channel (0 for all channels or put the channel number you would like to control)
HINSTANCE hGetProcIDDLL=NULL;          // Define dll handler

/* Load DLL into memory */
hGetProcIDDLL = LoadLibrary(TEXT("mfcs_c.dll"));

/* Declare pointers on dll functions */
init dll_init;
purgeOn dll_purgeOn;
purgeOff dll_purgeOff;
serial dll_serial;
close dll_close;
setAuto dll_setAuto;
readChannel dll_readChannel;
setAlpha dll_setAlpha;

/* Link dll pointers with functions prototype */
dll_init = (init)GetProcAddress(hGetProcIDDLL, "mfcsez_initialisation");
dll_serial = (serial)GetProcAddress(hGetProcIDDLL, "mfcs_get_serial");
dll_purgeOn = (purgeOn)GetProcAddress(hGetProcIDDLL, "mfcs_set_purge_on");
dll_purgeOff = (purgeOff)GetProcAddress(hGetProcIDDLL, "mfcs_set_purge_off");
dll_close = (close)GetProcAddress(hGetProcIDDLL, "mfcs_close");
dll_setAuto = (setAuto)GetProcAddress(hGetProcIDDLL, "mfcs_set_auto");
dll_readChannel = (readChannel)GetProcAddress(hGetProcIDDLL, "mfcs_read_chan");
dll_setAlpha = (setAlpha)GetProcAddress(hGetProcIDDLL, "mfcs_set_alpha");

/* Define variables used for MFCS device */
unsigned long mfcsHandle;
unsigned short mySerial;
float read_pressure;
unsigned short chrono;
int loop_index;


if (hGetProcIDDLL != NULL) {        // If dll loaded
    std::cout << "mfcs_c.dll is loaded" << std::endl;

    /* Initialize device */
    if (dll_init != NULL) {         // Check if function was properly linked to the dll file
        /* Initialize the first MFCS in Windows enumeration list */
        mfcsHandle = dll_init(0);
        /* After the initialization we need to add a delay of 500ms to make sure that the USB communication is properly established */
        Sleep(500);
        std::cout << "MFCS initialized" << std::endl;
    }

    /* Read device serial number */
    if (dll_serial != NULL) {
        /*Get the serial number of the MFCS*/
        dll_serial(mfcsHandle, &mySerial);
        std::cout << "MFCS SN: " << mySerial << std::endl;
    }

    /* Set pressure regulation servitude coefficient */
    if (dll_setAlpha != NULL) {
        dll_setAlpha(mfcsHandle ,pressureChannel, 4);       // Default value (just after power on) is 0 
    }                                                       // Alpha value has to be grather than 0 in order to regulate pressure

    /* Change and read pressure every second until reaching 'target_pressure' value */
    for (loop_index = int(start_pressure); loop_index<target_pressure; loop_index++){
        dll_setAuto(mfcsHandle,pressureChannel,float(loop_index));               // Set required output pressure value         
        Sleep(1000);                                                             // Wait 1 s
        dll_readChannel(mfcsHandle, pressureChannel, &read_pressure, &chrono);   // Get the pressure value on the specified channel
        std::cout << "Set pressure at: " << loop_index << "mbar" << "; Read pressure: " << read_pressure
            << "mbar" << std::endl;                                              // Display pressure setpoint and channel pressure value
    }

    /* Close MFCS session */
    if (dll_close != NULL) {
        dll_close(mfcsHandle);
        std::cout << "MFCS closed" << std::endl;
    }
}

/* Release the DLL */
FreeLibrary(hGetProcIDDLL);
std::cout << "mfcs_c.dll unloaded" << std::endl;

/* Exit application */
system("PAUSE");

return EXIT_SUCCESS;

}

基本上我已尝试过许多导入函数的排列,以及任何包含无符号字符或指针的函数,我无法弄清楚如何映射。

非常感谢大卫推动我从我的生活中变得更有用。

注意:有助于我的一个例子是基于上面的C ++代码的明确指令,用于引入mfcs_get_serial(unsigned long int句柄,     无符号短*序列)到C#。

1 个答案:

答案 0 :(得分:0)

请注意,此答案是针对问题的原始版本编写的,然后才会将其编辑为其他问题。我不是冒着编辑战争的风险,而是按原样离开。

在Windows上的C ++ long是32位类型。所以

unsigned long __stdcall mfcs_initialisation(unsigned short serial);

应该是

[DllImport("mfcs_c_64.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint mfcs_initialisation(ushort serial);

根据提供的信息,其他功能更难翻译。第二个参数可以是单个值,也可以是数组。前者更有可能。所以翻译应该是

[DllImport("mfcs_c_64.dll", CallingConvention = CallingConvention.StdCall)]
public static extern byte mfcs_get_serial(uint handle, out ushort us);