这里总结一些.net和c++DLL交互,这里是非托管的形式.

c++ DLL 部分.

关于如何创建c++DLL , 呃, 就是注意
#ifdef YWSCOLLOCATIONDLL_EXPORTS
#define YWSCOLLOCATIONDLL_API __declspec(dllexport)
#else
#define YWSCOLLOCATIONDLL_API __declspec(dllimport)
#endif

这个宏定义,在后面修改的时候,记得把属性里面的 也改掉

而且注意,最好使用 __stdcall c的方式做约束

yws_collocationDLL.h


#ifdef YWSCOLLOCATIONDLL_EXPORTS
#define YWSCOLLOCATIONDLL_API __declspec(dllexport)
#else
#define YWSCOLLOCATIONDLL_API __declspec(dllimport)
#endif


//////////////////////////注意头文件的引用
#include <windows.h>
// TODO: 在此处引用程序需要的其他头文件
#include <iostream>
#include <stdlib.h>
#include <wchar.h>


// 此类导出自 yws_collocationDLL.dll
class YWSCOLLOCATIONDLL_API CywscollocationDLL {
public:
	CywscollocationDLL(void);
	// TODO:  在此添加您的方法。
};

extern YWSCOLLOCATIONDLL_API int nywscollocationDLL;

YWSCOLLOCATIONDLL_API int fnywscollocationDLL(void);



#pragma region //另一种方式定义一个函数.这里传入普通的数值
EXTERN_C YWSCOLLOCATIONDLL_API int __stdcall yws_AddMethod(int a, int b);
//EXTERN_C YWSCOLLOCATIONDLL_API int yws_AddMethod(int a, int b);
#pragma endregion


//c++ 为wchar_t 对应c# char 类型..
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall WriteString(wchar_t* content);

//c++中,传入const char*  c#中传入string....
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall StringTochar(LPCTSTR content);

//这里使用传出字符串..
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall Cpp_PrintString(char charPtrLen[]);//char* charPtrLen


//指针的传递.
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall AddPtr(int *i);

//数组的传递.
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall AddIntArray(int *firstElement,int arrayLenght);

//数组传递方式二 不透明指针
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall AddIntArrayPtr(int *firstElementBuffer, int ArrayLenght);

//数组赋值
extern YWSCOLLOCATIONDLL_API int IntPtrLenght;

int * artptr;
EXTERN_C YWSCOLLOCATIONDLL_API int* __stdcall GetArray();

//函数指针
typedef void(_stdcall *CsCallBackMethod)(int tick);
EXTERN_C YWSCOLLOCATIONDLL_API void SetCallBack(CsCallBackMethod method);


//结构体的传递.
struct Vector3
{
   float x, y, z;
};

EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall SendStructFromCsToCPP(Vector3 vector);

//结构体指针的传入.
EXTERN_C YWSCOLLOCATIONDLL_API void __stdcall SendStructFromCsToCpp_ptr(Vector3 *vector);

//这里做一个比较复杂点的结构体的传入.


struct IStripe3DPoint
{
	float u;
	float v;
	float x;
	float y;
	float z;
	unsigned char R;
	unsigned char G;
	unsigned char B;

	float p3x;
	float p3y;
	float p3z;
	int ID;

};
//struct LPoint3d {
//	float x; float y; float z;
//};

IStripe3DPoint *Lstrio_ptr;
EXTERN_C YWSCOLLOCATIONDLL_API IStripe3DPoint * __stdcall SendStripD3Point();
yws_collocationDLL.cpp
// 这是导出变量的一个示例
YWSCOLLOCATIONDLL_API int nywscollocationDLL=0;

// 这是导出函数的一个示例。
YWSCOLLOCATIONDLL_API int fnywscollocationDLL(void)
{
    return 42;
}


//这是已导出类的构造函数。
//有关类定义的信息,请参阅 yws_collocationDLL.h
CywscollocationDLL::CywscollocationDLL()
{
    return;
}

 YWSCOLLOCATIONDLL_API int __stdcall yws_AddMethod(int a, int b)
{
	 return a + b;
}

 YWSCOLLOCATIONDLL_API void __stdcall WriteString(wchar_t* content)
 {

	 int num = WideCharToMultiByte(CP_OEMCP, NULL, content, -1, NULL, 0, NULL, FALSE);
	 char *pchar = new char[num];
	 WideCharToMultiByte(CP_OEMCP, NULL, content, -1, pchar, num, NULL, FALSE);

	  cout << pchar << endl;
 }
 YWSCOLLOCATIONDLL_API void __stdcall StringTochar(LPCTSTR content)
 {
	 string sConts = LPSTR(content);
	 
	 cout << sConts.c_str() << endl;
 }

 YWSCOLLOCATIONDLL_API void __stdcall Cpp_PrintString(char charPtrLen[])
 {
	 char buf[] = "你好,我是在DLL中赋值成功的字符串..";
	
	 memcpy(charPtrLen,buf, sizeof(buf));

	 /*for (int i = 0; i < sizeof(buf); i++)
	 {
		 *charPtrLen++ = buf[i];
	 }*/
	
 }


 YWSCOLLOCATIONDLL_API void __stdcall AddPtr(int *i)
 {
	 (*i)++;
 }

 YWSCOLLOCATIONDLL_API void __stdcall AddIntArray(int *firstElement, int arrayLenght)
 {
	 int *currentPointer = firstElement;
	 for (int i = 0; i < arrayLenght; i++)
	 {
		 cout << currentPointer[i] << " ";
	 }
	 cout << endl;

 }

 YWSCOLLOCATIONDLL_API void __stdcall AddIntArrayPtr(int *firstElementBuffer,int ArrayLenght)
 {
	 for (int i = 0; i < ArrayLenght; i++)
	 {
		 cout << firstElementBuffer[i] << " ";
	 }
	 cout << endl;
	 cout << "不透明指针输出完毕." << endl;
 }


 YWSCOLLOCATIONDLL_API int* __stdcall GetArray()
 {
	 artptr = new int[10];
	 for (int i = 0; i < 10; i++)
	 {
		 artptr[i] = i;
	 }
	 return artptr;
 }

 YWSCOLLOCATIONDLL_API void SetCallBack(CsCallBackMethod method)
 {
	 int tick = rand()/20;
	 method(tick);
 }

 YWSCOLLOCATIONDLL_API void __stdcall SendStructFromCsToCPP(Vector3 vector)
 {
	 cout << "get vector3 int cpp, x: " << vector.x << " ,y: " << vector.y << " ,z: " << vector.z << endl;
 }

 YWSCOLLOCATIONDLL_API void __stdcall SendStructFromCsToCpp_ptr(Vector3 *vector)
 {

	 vector->x += 100;
	 cout << "get vector3 int cpp, x: " << vector->x << " ,y: " << vector->y << " ,z: " << vector->z << endl;

 }

 YWSCOLLOCATIONDLL_API IStripe3DPoint* __stdcall SendStripD3Point()
 {
	 if (Lstrio_ptr != NULL)
	 {
		 delete[] Lstrio_ptr;
		 Lstrio_ptr = NULL;
	 }
	 Lstrio_ptr = new IStripe3DPoint[10];
	 for (int i = 0; i < 10; i++)
	 {
		 Lstrio_ptr[i].B = i;
		 Lstrio_ptr[i].G = 3;
		 Lstrio_ptr[i].R = 98;

		 Lstrio_ptr[i].x = Lstrio_ptr[i].y = Lstrio_ptr[i].z = i * 4;
		 Lstrio_ptr[i].p3x = Lstrio_ptr[i].p3y = Lstrio_ptr[i].p3z = i * 5;
	 }

	 return Lstrio_ptr;
 }

到此,编译 输出
在这里插入图片描述

.net 程序里,对DLL里api的封装

    //此函数引入cpp dll,作为c++dll的映射函数..
    public class Mvpi_yws_DLL
    {
        //数值相加
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"yws_AddMethod")]
        public extern static int yws_AddMethod(int a, int b);

        //w_char字符传递
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"WriteString")]
        extern unsafe static void WriteString(char* contend);

        public static unsafe void yws_WriteString(string content)
        {

            fixed (char* p = &(content.ToCharArray()[0]))
            {
                WriteString(p);
            }

        }

        //字符串传递
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"StringTochar")]
        extern unsafe static void StringTochar(char* contend);
        public static unsafe void yws_StringTochar(string content)
        {
            char* outF = (char*)System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(content).ToPointer();
            StringTochar(outF);
        }

        //字符串输出
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"Cpp_PrintString")]
        extern static void  Cpp_PrintString(StringBuilder charPtrLen);
        //销毁
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"DesTroystr")]
        extern unsafe static void DesTroystr();

        public static  void yws_cppPrintStr()
        {
            StringBuilder strb = new StringBuilder();
            strb.Capacity = 1000;
            Cpp_PrintString(strb);
            Console.WriteLine(strb);

        }
      


        //指针传递
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"AddPtr")]
        public extern unsafe static void AddPtr(int* contend);
        public static unsafe void yws_addPtr(ref int i)
        {
            int temp = i;
            AddPtr(&temp);
            i = temp;
        }

        //数组传递.方式一
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"AddIntArray")]
        public extern unsafe static void AddIntArray(int* firstElement, int arrayLenght);

        public static unsafe void yws_AddIntArray(int[] buffer, int bufferLenght)
        {
            bufferLenght = buffer.Length;
            fixed (int* k = &buffer[0])
            {
                AddIntArray(k, bufferLenght);
            }

        }

        //数组传递方式二 这里使用不透明指针来完成数组传入...
        [DllImport(@"YWSCOLLOCATIONDLL.dll",EntryPoint = @"AddIntArrayPtr")]
        public extern unsafe static void AddIntArrayPtr(IntPtr firstElementBuffer, int ArrayLenght);
        public static void yws_AnotherMethod(int[] buffer)
        {
            int bufferLen = buffer.Length;
            GCHandle dllfind = GCHandle.Alloc(buffer,GCHandleType.Pinned);
            if(dllfind.IsAllocated == true)
            {
                AddIntArrayPtr(dllfind.AddrOfPinnedObject(),bufferLen);
            }
            else
            {
                Console.WriteLine("地址分配失败..");
            }
            dllfind.Free();
          
        }


        //数组赋值.
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"GetArray")]
        public extern unsafe static int* GetArray();

        public unsafe static void yws_GetArray()
        {
            int* pArrayPointer = null;
            pArrayPointer = GetArray();
            for(int i=0;i<10;i++)
            {
                Console.Write(pArrayPointer[i].ToString()+" ");
            }
        }

        //函数指针与委托.
        public delegate void CsCallBackMethod(int tick);
       
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"SetCallBack")]
        public extern  static void SetCallBack(CsCallBackMethod method);

      
        static CsCallBackMethod callBack;
        static void CsCallBackFuntion(int tick)
        {
            Console.WriteLine(tick.ToString());
        }

        public static void yws_SetCallBack()
        {
            callBack = CsCallBackFuntion;
            SetCallBack(callBack);
        }


        //传递结构体.
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"SendStructFromCsToCPP")]
        public extern static void SendStructFromCsToCPP(Vector3 vector);

        //传递结构体指针,并修改之..
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"SendStructFromCsToCpp_ptr")]
        public extern static void SendStructFromCsToCpp_ptr(ref Vector3 vector);


        //自定义结构体数组测试.
        [DllImport(@"YWSCOLLOCATIONDLL.dll", EntryPoint = @"SendStripD3Point")]
        public extern unsafe static IStripe3DPoint* SendStripD3Point();

        public static unsafe void yws_sendStripD3Point()
        {
            IStripe3DPoint* pArrayPointer = null;
            pArrayPointer = SendStripD3Point();
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("数组: {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}",i, pArrayPointer[i].x, pArrayPointer[i].y, pArrayPointer[i].z,
                    pArrayPointer[i].R, pArrayPointer[i].B, pArrayPointer[i].G,
                    pArrayPointer[i].p3x, pArrayPointer[i].p3y, pArrayPointer[i].p3z));
            }
        }

    }


    [StructLayout(LayoutKind.Sequential)]
    public struct Vector3
    {
        public float x, y, z;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IStripe3DPoint
    {
        public float u;
        public float v;
        public float x;
        public float y;
        public float z;

        public byte R;
        public byte G;
        public byte B;

        public float p3x;
        public float p3y;
        public float p3z;
        public int ID;

    };


创建.net 程序,将上面生成的DLL放到 和 .exe 目录里, .net 部分调用
 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("调用C++非托管DLL 开启\r\n");

            int result = Mvpi_yws_DLL.yws_AddMethod(10,20);

            Console.WriteLine("计算结果: "+ result.ToString());

            string tem = "程序运行,性能开启测试....\r\n";
            Mvpi_yws_DLL.yws_WriteString(tem);

            Mvpi_yws_DLL.yws_cppPrintStr();

            Mvpi_yws_DLL.yws_StringTochar("程序运行,性能开启测试二.....");

            int result2 = 15;
            Mvpi_yws_DLL.yws_addPtr(ref result2);
            Console.WriteLine("\r\n 计算结果:"+result2.ToString()+"\r\n");

            //数组
            int[] buf = { 1,23,45,66,77,88};
            Mvpi_yws_DLL.yws_AddIntArray(buf, buf.Length);

            //数组赋值二:
            int[] buf2 = { 23,44,55,657,3,8};
            Mvpi_yws_DLL.yws_AnotherMethod(buf2);

            //获取赋值之后的数据...
            Console.WriteLine();
            Mvpi_yws_DLL.yws_GetArray();
            Console.WriteLine();

            //函数指针的处理..
            Mvpi_yws_DLL.yws_SetCallBack();

            //传递结构体..
            Vector3 vector = new Vector3() { x = 10,y =33,z =99 };
            Mvpi_yws_DLL.SendStructFromCsToCPP(vector);

            //传递结构体指针
            Mvpi_yws_DLL.SendStructFromCsToCpp_ptr(ref vector);
            Console.WriteLine("改变之后的数值: "+vector.x.ToString());

            //自定义结构体指针数组..
            Console.WriteLine();
            Mvpi_yws_DLL.yws_sendStripD3Point();

            Console.WriteLine("\r\n调用C++非托管DLL 结束");
            Console.ReadKey();

        }
    }

运行:
在这里插入图片描述
这个就是效果图, 大家记得把**.net程序 要 勾选 不安全代码 选项** ,
有了这个, .net 和c++基本上,就可以完全不用担心了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章