這裏總結一些.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++基本上,就可以完全不用擔心了

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