C#中调用C++的dll的参数为指针类型的导出函数

转载 2011年08月12日 14:07:16

         严格来说这篇文章算不上C++范围的,不过还是挂了点边,还是在自己的blog中记录一下吧。

         C++中使用指针是家常便饭了,也非常的好用,这也是我之所以喜欢C++的原因之一。但是在C#中就强调托管的概念了,指针就不用想了。本来如果就在C#的世界里面写代码,也还算舒服,但是万事万物总有联系,这不,现在公司的另外一个用C#作的项目就碰到问题了,要调用之前用C++写的一个DLL中的一些函数,很多函数的参数都是指针类型的,这下可麻烦咯,公司里做C#的都是刚起步,C++又只有我最熟悉,这项技术研究工作又光荣的落到我身上。

        我对C#也不甚熟悉,所以也许我的方法不一定是最直接的,但是测试的结果是满足了这个调用需要了的。下面我就详细介绍一下。

        使用unsafe、fix等关键字应该是能够实现的,但是他们项目组要求不用这个,所以我也没深入去试验。除了这个方法,应该来说是有两个思路的,第一个思路可能看起来比较直接,使用ref,ref这个关键字似乎有点特殊性,字面上理解似乎应该和C++中的引用类型相对应,不过似乎它还是有一定特殊性的,貌似以前看到过一篇文章说ref会自己去判断是引用类型还是指针,我尝试了一下,果然是可行的。但是对于有二级指针的情况ref也就不灵了~这就导出了我的另一个思路,使用Marshal。

下面我们还是代码说明问题:
以下是C++DLL中的代码片断,主要是使用到的两个结构的定义,以及导出函数TestFunction的定义。

C++ DLL中的代码片断
#pragma pack
(push)
#pragma pack(1)
typedef struct EmmStruct {
    int len;
} EMMSTRUCT, *LPEMMSTRUCT;

typedef struct MyStruct {
    int iParam;
    long size;
    LPEMMSTRUCT lpEmmStructArr;
} MYSTRUCT, *LPMYSTRUCT;
#pragma pack(pop)

extern "C" void __declspec(dllexport) __stdcall  TestFunction(LPMYSTRUCT lpMyStruct)
{
    lpMyStruct->iParam = 100;
    lpMyStruct->size = 10;
    lpMyStruct->lpEmmStructArr = new EMMSTRUCT[lpMyStruct->size];
    for(int i=0;i<lpMyStruct->size;i++) {
        lpMyStruct->lpEmmStructArr[i].len = i;
    }
}


那么再来看看C#中调用的代码:
C#中调用的代码片断using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;      //使用C#导入dll必须的

namespace csharptest
{
    //StructLayout和FieldOffset这些设置不是必须的,只是为了防止对齐的问题最好加上,这样自己心里有数对齐到哪一位
    [StructLayout(LayoutKind.Explicit)]
    public struct EmmStruct
    {
        [FieldOffset(0)]
        public int len;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct MyStruct
    {
        [FieldOffset(0)]
        public int iParam;
        [FieldOffset(4)]
        public int size;
        [FieldOffset(8)]
        public IntPtr ptrEmmStruct;
    }

    class Program
    {
         // dll中导出函数的声明
        [DllImport("dllforcsharp.dll", CallingConvention=CallingConvention.Winapi)]
        public extern static void TestFunction(IntPtr ptr);

        static void Main(string[] args)
        {
            try
            {
                MyStruct s = new MyStruct();
                IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(s));
                Marshal.StructureToPtr(s, ptr, false);

                TestFunction(ptr);

                s = (MyStruct)Marshal.PtrToStructure(ptr, typeof(MyStruct));

                EmmStruct ret;
                for (int i = 0; i < s.size; i++)
                {
                    IntPtr ptr2 = new IntPtr(s.ptrEmmStruct.ToInt32() + 4 * i);
                    ret = (EmmStruct)Marshal.PtrToStructure(ptr2, typeof(EmmStruct));
                }

                Marshal.FreeHGlobal(ptr);
            }
            catch (Exception e)
            {
                string str = e.Message;
            }
            finally
            {
            }
        }
    }
}


C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)

一:首先什么是IntPtr 先来看看MSDN上说的:用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型。对于它的解释,这个哥...
  • u010159842
  • u010159842
  • 2016年06月27日 10:49
  • 2628

如何生成DLL文件并导出函数及如何在C++或C#中调用DLL中导出的函数

关于DLL的含义和优点,不是本文讨论的重点,这里我们仅讨论如何用C++生成DLL文件,并导出函数。 首先:在VS中创建工程的时候,要选择VC++(我只会用C++来生成DLL文件)语言,然后选择w...
  • adi_1987
  • adi_1987
  • 2016年12月05日 13:34
  • 1166

c#调用C++写的DLL,传递二维指针参数

c++中函数声明如下: bool Test(float** arr,int rows,int cols); C#无法直接调用这种参数的函数,C#中你描述的那种二维数组,本质上跟一维数组...
  • CNHK1225
  • CNHK1225
  • 2016年11月10日 14:14
  • 1457

C# 调用C++ dll 指向指针的指针 对应数据类型

dll 方法:            int ADL_Display_DisplayMapConfig_Get (int iAdapterIndex, int *lpNumDispl...
  • evanyanglibo
  • evanyanglibo
  • 2015年08月27日 15:58
  • 1144

C# 调用C/C++ Dll(参数含char*指针,返回char*指针)

动态库: //MyPointDll.h extern"C" _declspec(dllexport) char* strcpyTest(char* dest,char* sour);
  • youqingyike
  • youqingyike
  • 2015年08月16日 12:12
  • 6438

C#与C++的混合编程 之二 使用非托管dll 导出标准函数

C#与C++的混合编程 之二  使用非托管dll 导出标准函数
  • fang1192801693
  • fang1192801693
  • 2015年11月29日 12:40
  • 866

C# 调用Dll 传递字符串指针参数

用C#调用VC写的dll,传递参数给dll,如果是非托管代码,调用起来有点麻烦。所以把把参数转换成非托管代码的指针参数,然后再传递给dll。 using System.Runtime.Int...
  • yongyong521
  • yongyong521
  • 2015年12月04日 18:02
  • 1123

C#调用C++DLL的小总结8---C++Dll中函数返回字符串指针

 C#调用C++DLL的小总结8---C++Dll中函数返回字符串指针 在这个系列的“C#调用C++DLL的小总结6---C++Dll中指针的释放问...
  • u011555996
  • u011555996
  • 2017年04月19日 11:16
  • 1761

C#调用C写的DLL二级指针传递方法

最近在做一项目需要调用第3方DLL(c写的),其中有个参数是2级指针,查了很多资料终于搞定 1、函数原形   方法原式:   int Quest_goodsA(CHAR* flowno ,CHAR...
  • boythl
  • boythl
  • 2014年11月27日 16:56
  • 1066

c#调用c语言dll,形参有char*

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin...
  • bejustice
  • bejustice
  • 2014年07月30日 11:17
  • 1989
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#中调用C++的dll的参数为指针类型的导出函数
举报原因:
原因补充:

(最多只允许输入30个字)