본문 바로가기

C++(oF)

c++ 의 포인터 데이터를 c# 으로 전달하기



c++ 로 작성한 간단한 문자열을 포인터 로 반환 하는 함수 이다. 이때 & 로 데이터를 길이를 전달 한다.

#define EXTERN __declspec(dllexport)
extern "C"
{
    //함수를 통해 데이터 포인터를 전달 할때 사이즈 길이를 함께 전달 하는 방법
    //Call by Reference 로 전달 한다.

    EXTERN 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;
    }
}



C4996 에러를 간단히 피하는 방법은 


#pragma warning(disable:4996)







c# 코드는 아래와 같다.

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


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

메모리 해제도 잊지 말자.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace CSClient
{
    class Program
    {
        [DllImport("ExportDLLTest_debug", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr GetByte(out int size);


        [DllImport("kernel32")]
        static extern IntPtr LocalFree(IntPtr mem);

        static void Main(string[] args)
        {
            int size = 0;
            IntPtr data = GetByte(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("free");
                LocalFree(data);
            }



            string result = Encoding.Default.GetString(_receiveData);
            Console.WriteLine("string receive from native cpp : " + result);

            
        }
    }
}