• C#调用C++动态库数据类型转换问题


    C#调用C++比较常见的两种方式,一种是调用C++dll提供的接口,另一种直接调用C++提供的类,使用上更灵活一些。
    其他的方式我也不知道了。
    这里暂时只讲第一种方式,这种方式用得比较多。

    传入参数

    传入数值类型的参数

    这个就比较直接了,没什么变化,接口是int型,调用处也是int型,这种大家都有的类型传递起来就比较方便。
    举个最简单的例子:
    .h文件中

    extern "C" __declspec(dllexport) bool setInt(int a);
    

    .cpp文件中:

    bool setInt(int a)
    {
        cout << a << endl;
        return true;
    }
    

    .cs文件中:

    [DllImport("MyDll.dll")]
    static extern bool setInt(int a);
    
    int a = 1;
    setInt(a);
    

    传入字符串类型的参数

    c++中使用char*参数类型,在C#中可以选择使用string或者StringBuilder
    接口声明:

    extern "C" __declspec(dllexport) bool setString(char* a);
    

    定义:

    bool setString(char* a)
    {
        cout << a << endl;
        return true;
    }
    

    调用处:

    [DllImport("MyDll.dll")]
    static extern bool setString(StringBuilder a);
    
    [DllImport("MyDll.dll")]
    static extern bool setString(string a);
    
    string b = "ceshi";
    setString(b);
    StringBuilder sb = new StringBuilder("shiyixia");
    setString(sb);
    

    传入结构体类型的参数

    结构体的传递需要使用指针,接口处可以定义为void*类型的参数,也可以使用结构体指针,C#处传递参用IntPtr类型,传指针都是用这个类型就可以了。
    结构体定义:

    typedef struct __RESULT_STRUCT__
    {
        char name[256];  // 这边注意长度要和接口调用处统一起来
        int x;
        int y;
        int width;
        int height;
        double confidence;
    } RESULT_STRUCT, *P_RESULT_STRUCT;
    

    接口声明:

    extern "C" __declspec(dllexport) bool setStruct(P_RESULT_STRUCT d1);
    

    定义:

    bool setStruct(P_RESULT_STRUCT d)
    {
        cout << d->name << endl;
        cout << d->x << endl;
        cout << d->y << endl;
        cout << d->width << endl;
        cout << d->height << endl;
        cout << d->confidence << endl;
        return false;
    }
    

    调用处:

    [StructLayout(LayoutKind.Sequential)]
    private struct Result
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string name;
        public int x;
        public int y;
        public int width;
        public int height;
        public double confidence;
    }
    
    [DllImport("MyDll.dll")]
    static extern bool setStruct(IntPtr result);
    
    Result d = new Result
    {
        name = "测试一下name",
        x = 101,
        y = 102,
        width = 103,
        height = 104,
        confidence = 0.55
    };
    IntPtr dPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)));
    Marshal.StructureToPtr(d, dPtr, false);
    setStruct(dPtr);
    Marshal.FreeHGlobal(dPtr);
    

    传入数组类型的参数

    传入元素为数值型的数组

    数组的传递需要使用指针,接口处都可以定义为void*类型的参数,也可以定义为具体的类型的指针,C#处传递参数用IntPtr类型。
    int型数组举例,其他都是差不多的:
    接口声明:

    extern "C" __declspec(dllexport) bool getArray(void* data, int len);
    

    定义:

    bool getArray(void* data, int len)
    {
        int* d = (int*)data;
        for (int i = 0; i < len; i++)
        {
    	cout << d[i] << endl;
        }
        return true;
    }
    

    调用处:

    int[] c = new int[] { 1, 2, 3, 4 };
    IntPtr cPtr = Marshal.AllocHGlobal(sizeof(int) * c.Length);
    Marshal.Copy(c, 0, cPtr, c.Length);
    getArray(cPtr, c.Length);
    Marshal.FreeHGlobal(cPtr);
    
    [DllImport("MyDll.dll")]
    static extern bool getArray(IntPtr data, int len);
    

    传入结构体数组

    和传入单个的结构体也差不多,就是把结构体一个个按顺序排排好。
    接口声明:

    extern "C" __declspec(dllexport) bool setStructArray(P_RESULT_STRUCT d2, int len);
    

    定义:

    bool setStructArray(P_RESULT_STRUCT d2, int len)
    {
        for (int i = 0; i < len; i++)
        {
            RESULT_STRUCT s = d2[i];
            cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
            cout << s.name << endl;
            cout << s.x << endl;
            cout << s.y << endl;
            cout << s.width << endl;
            cout << s.height << endl;
            cout << s.confidence << endl;
            cout << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl;
        }
        return true;
    }
    

    调用处:

    Result e = new Result
    {
        name = "测试两下name",
        x = 201,
        y = 202,
        width = 203,
        height = 204,
        confidence = 0.66
    };
    
    Result[] f = new Result[] { d, e };
    IntPtr g = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)) * f.Length);
    Marshal.StructureToPtr(f[0], g, false);
    Marshal.StructureToPtr(f[1], g + Marshal.SizeOf(typeof(Result)), false);
    setStructArray(g, f.Length);
    Marshal.FreeHGlobal(g);
    
    [DllImport("MyDll.dll")]
    static extern bool setStructArray(IntPtr result, int len);
    

    传出参数

    传出数值型的参数

    接口定义处参数类型加&,调用处用ref
    接口声明:

    extern "C" __declspec(dllexport) bool getInt(int& a);
    

    定义:

    bool getInt(int& a)
    {
        a = 202;
        return true;
    }
    

    调用:

    int h = 0;
    getInt(ref h);
    Console.WriteLine(h);
    
    [DllImport("MyDll.dll")]
    static extern bool getInt(ref int a);
    

    传出字符串类型的参数

    参数使用char*,调用处使用StringBuilder
    接口声明:

    extern "C" __declspec(dllexport) bool getString(char* a);
    

    定义:

    bool getString(char* a)
    {
        string b = "ceshi测试";
        strcpy_s(a, b.length() + 1, b.c_str());
        return true;
    }
    

    调用:

    [DllImport("MyDll.dll")]
    static extern bool getString(StringBuilder sb);
    
    StringBuilder i = new StringBuilder(1024);
    getString(i);
    Console.WriteLine(i);
    

    传出结构体类型的参数

    接口声明:

    extern "C" __declspec(dllexport) bool getStruct(P_RESULT_STRUCT data);
    

    定义:

    bool getStruct(P_RESULT_STRUCT data)
    {
        char a[123] = "这是新的结构体";
        strcpy_s(data->name, a);
        data->x = 122;
        data->y = 123;
        data->width = 124;
        data->height = 125;
        data->confidence = 0.98;
        return true;
    }
    

    调用:

    [DllImport("MyDll.dll")]
    static extern bool getStruct(IntPtr result);
    
    IntPtr k = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Result)));
    getStruct(k);
    Result l = (Result)Marshal.PtrToStructure(k, typeof(Result));
    Console.WriteLine("{0},{1},{2},{3},{4},{5}", l.name, l.x, l.y, l.width, l.height, l.confidence);
    

    传出数组类型的参数

    传出数值型数组

    接口声明:

    extern "C" __declspec(dllexport) bool getIntArray(int* data, int& len);
    

    定义:

    bool getIntArray(int* data, int& len)
    {
        len = 10;
        for (int i = 0; i < len; i++)
        {
            data[i] = i;
        }
        return true;
    }
    

    调用:

    [DllImport("MyDll.dll")]
    static extern bool getIntArray(IntPtr data, ref int len);
    
    IntPtr m = Marshal.AllocHGlobal(sizeof(int) * 100);
    int n = 0;
    getIntArray(m, ref n);
    int[] p = new int[n];
    Marshal.Copy(m, p, 0, n);
    for (int o = 0; o < n; o++)
        Console.WriteLine(p[o]);
    

    传出字符串型数组

    未完待续

    传出结构体型数组

    未完待续

  • 相关阅读:
    [Tips] Resolve error: server certificate verification failed.
    [Tips] bzr Import error
    NPAPI命休矣
    [Buzz Today]2013.08.18
    [Tips]Fix node.js addon build error: "gyp: binding.gyp not found"
    The.first.glance.at.linux.commands
    [Idea Fragments]2013.08.08
    Linux利器:WinSCP,Putty,pscp和psftp
    本博客已经迁移去http://blog.brightwang.com/
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/yutou2016/p/14670902.html
Copyright © 2020-2023  润新知