튜토리얼

C++ Dll 에서 간단하 문자열을 포인터로 C#에 전달하는 내용이다. 


2015/07/15 - [잡다한 자료(번역)/Unity3D] - Unity 과 DLL을 : C#을 (managed) 및 C++(unmanaged)

(C++ C# Dll 만드는 법)


보스전

C++ Dll 이다. 간단한 문자열을 포인터로 반환 하는 함수이며, 이떄 &로 데이터의 길이를 전달한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifdef FUNCDLL_EXPORT
#define FUNCDLL_API __declspec(dllexport)
#else
#define FUNCDLL_API __declspec(dllimport)
#endif
 
extern "C"
{
    //함수를 통해 데이터 포인터를 전달 할때 사이즈 길이를 함께 전달 하는 방법
    //Call by Reference 로 전달 한다.
 
    FUNCDLL_EXPORT char* GetByte(int &size)
    {
        string str = "hello world";
        size = str.size();
        char* data = new char[size];
        strcpy(data , str.c_str());
 
        cout << "end function" << endl;
        return data;
    }
}
cs


strcpy 를 쓰면 머시기머시기 하며 C4996 에러가 나는데 (strcpy_s 를 쓰라고 하는 에러)


#pragma warning(disable:4996)


한 줄 딱 쓰면 에러가 제외된다.



C# 코드는 아래와 같다.

방법은 2가지 인데, 하나는 마샬링을 이용하는 방법, 다른 하나는 unsafe 블럭을 통해 직접 접근 하는 방법이다.


만약 PInvokeStackImbalance" Exception 이 발생한다면 , CallingConvention=CallingConvention.Cdecl 를 DllImport 에 붙인다.

메모리 해제도 잊지 말자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using MMF;
 
namespace UnityTest
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32")]
        static extern IntPtr LocalFree(IntPtr mem);
        private void btnFbxOpen_Click(object sender, EventArgs e)
        {
            TCPServer.UnitySend("CreateCube", TCP.CommandType.Exit);
            MMF.Database.Binarywrite("10, 10, 10"20);
            MMF.Database.Binaryread();
 
            int size = 0;
            IntPtr data = Database.DataRe(out size);
            Console.WriteLine("string Length : " + size);
 
            byte[] _receiveData = new byte[size];
 
            try
            {
                if (true//마샬링을 이용하여 포인터를 배열로 전환 하는 방법
                {
                    Marshal.Copy(data, _receiveData, 0, _receiveData.Length);
                }
                else
                {
                    unsafe //unsafe 이용하여 직접 포인터 변수에 접근 하는 방법
                    {
                        Console.WriteLine("use unsafe block");
 
                        byte* ptrData = (byte*)data.ToPointer();
                        for (int i = 0; i < size; i++)
                        {
                            _receiveData[i] = (byte)ptrData[i];
                        }
                    }
                }
            }
            finally
            {
                //메모리 해제
                Console.WriteLine(true);
                LocalFree(data);
            }
 
            string result = Encoding.Default.GetString(_receiveData);
            
            Console.WriteLine("string receive from native cpp : " + result);
        }
    }
}
cs



엔딩 후 추가내용...

추가 설명 : 

C# unsafe 키원드 사용법

참조 사이트


예제는 댓글로 필요하다는 분이 있으면 추가하겠습니다~


  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기