한참을 삽질하고, 보내다가 어떤 블로그를 보니, 하고싶은 것이 된다. 

블로그 정리로 시작하자. 



01. DLL Project 간단한 생성 방법은 이전에 작성한 posting 을 참조.

http://vbflash.net/900


02. Posting 하고자하는 내용 설명

 2.1 C와 C#에서의 커뮤니케이션 방법(통신방법)

...검색하다보니깐 -_- PDF로 나온다..


 Calling_C_Library_DLLs_from_C_sharp.pdf


-2013.09.30-

by 퓨림노


현재 Unity3D를 이용하여 증강현실 시스템을 개발중이다. Unity3D는 C#, Javascript의 언어를 사용한다. 

현재 기존에 개발하였던 모듈의 언어가 C,C++,Java 로 구성되어 있다. 그래서 난 C++ 로 구성되어 있는 클래스를 그대로 사용하기 위하여 C의 DLL 모듈로 만들어서 땡겨서 쓰려고 한다. 


이전에 Android <-> C의 통신을 위하여 native C를 사용해보았는데, C<->C# 또한 조금 다르게 코딩이 되어진다. 더군다나 DLL 로 만들어서 사용하기 때문에 디버깅은 미궁에 빠지게 된다. 


첫 경험이란게 정말 소중할 정도로. -_- 포스팅해두자. 난중에 되면 까먹는다. 


그래서 현재 아래의 방법을 이용하면 거진 하고 싶은 것은 할 수 있다. 라고 생각함. 

다른방법도 있지만 지금은 현재 완료되어 있는 부분부터 해결 하고 넘어가도록 하자. 


- 2013.09.27 - 

  금요일 밤인데, 집중해서 주절주절. by 퓨림노

   

     

03. C와 C#에서 다양한 방법을 통해 값을 넘겨주고 받자. 

    현재 Unity3D 의 C#코드에서 C코드를 사용하여 processing하고자 한다. 상황을 잘 이해 하였는가?


 3.0 C#에서 C의 native code 삽입하자.


// Library
	[DllImport("UnityPlugin")]
    public static extern void Scalars(double invar, ref double outvar);

    [DllImport("UnityPlugin")]
    public static extern void OneDArray(double [] anArray, int n);

    [DllImport("UnityPlugin")]
    public static extern void TwoDArray(double [,] a2dArray, int m, int n);

    [DllImport("UnityPlugin")]
    public static extern void TryComplex(Complex inputVar, ref Complex outputVar,
               [In, Out] Complex [] array, int n);

    [DllImport("UnityPlugin")]
    public static extern void MarshalStructC(ref marshalStruct pointerinStruct);
    
	[DllImport("UnityPlugin")]
    public static extern void FreeMarshalStructptr(ref marshalStruct pointerinStruct);

 - C#의 젤 상위에 DLL 을 import 한다고 작성하자.


 3.1 변수의 포인터를 이용하여 값을 넘겨주고 받자.

// 아래의 코드는 항상 들어가기 때문에 필수라 생각하자. 
#define EXPORT_API __declspec(dllexport)

//01. C side code
EXPORT_API void Scalars( double in, double *out ) {
		*out = in;
	}

// 02. C# side code
double invar = 5.0;
double outvar = 0.0;
Scalars(invar, ref outvar);		
Debug.Log( "invar = " + invar +  "outvar = " + outvar );		

포인터를 이용하여 invar의 값을 outvar 로 삽입이 되었다. 

C side에서 다르게 응용이 되어진다. 


 3.2 1차원 배열의 값을 주고 받자.

아래쪽 코드는 글자가 깨지는 관계로.....그냥 박스 상자에서 보시길. 

//01. C side code

EXPORT_API void OneDArray( double anArray[], int n ) {
for( int i=0; i<n; i++ ) {
anArray[i] = i;
}
};


// 02. C# side code

double [,] a2dArray = new double [3,2];
TwoDArray(a2dArray, a2dArray.GetLength(0), a2dArray.GetLength(1));
for( int i=0; i<3; i++) {
for( int j=0; j<2; j++ ){
Debug.Log( "array[" + i + "][" + j + "] = " + a2dArray[i,j] );
}

}


 3.3 2차원 배열을 주고 받자.
// 01. C side code
EXPORT_API void TwoDArray( double a2Array[], int m, int n ) {

		a2Array[0*n+0] = 1; // 0,0
		a2Array[1*n+0] = 2; // 1,0
		a2Array[2*n+1] = 3;	// 2,1
	}

// 02. C# side code
double [,] a2dArray = new double [3,2];				
        TwoDArray(a2dArray, a2dArray.GetLength(0), a2dArray.GetLength(1));
		for( int i=0; i<3; i++) {
			for( int j=0; j<2; j++ ){
				Debug.Log( "array[" + i + "][" + j + "] = " + a2dArray[i,j] );
			}
		}

 3.4 C,C#의 구조체를 주고 받자. 

// 01. C side code
struct myComplex {
	double re;
	double im;
};

EXPORT_API void TryComplex( myComplex inputVar, myComplex *outputVar, myComplex array[], int n ) {
		outputVar->re = ++inputVar.re;
		outputVar->im = ++inputVar.im;

		array[0].re = 99.0;
		array[0].im = 98.0;
		array[1].re = 97.0;
		array[1].im = 96.0;
	}

// 02. C# side code
Complex inputVar = new Complex();
		Complex outputVar = new Complex();
		Complex [] array = new Complex[3];
		inputVar.re = 1.0;
		inputVar.im = 2.0;
		TryComplex(inputVar, ref outputVar, array, array.GetLength(0));



 3.5 구조체의 동적할당을 이용하자. (미해결)

 - 다른 블로그 참조해서 해결하시기 바랍니다. 


<추가> Char/String 을 전달하는 방법

- 첨부파일을 참조하기 바람. 그리고 아래의 방법은 char을 사용하는 것.

// 01. C side code
void EXPORT_API ReadPort( char *filename ) {
		// for Read Port Number & Connect
	}

void EXPORT_API SendDataToSerialPort( char *ch ){
     if('q' == *ch) {
      }
	}

// 02. C# side code
	[DllImport("LibModule.dll")]	
	private static extern void ReadPort( char[] filename );

	[DllImport("LibModule.dll")]	
	private static extern void SendDataToSerialPort( char[] dir );


	void Start () {
		string str = "Port.txt";
		char[] szArr = str.ToCharArray();
		
		ReadPort (szArr);
		Debug.Log ("ReadPort");
	}

	void Update () {
		
		char[] ch = new char[1];
		
		if(Input.GetKeyUp(KeyCode.E)) { 				// Up
			Debug.Log ( Count++ + "KeyDown : E ");			
			ch[0] = 'e';
			SendDataToSerialPort(ch);
		}
	}



Reference


[1] htna 님의 블로그 ( http://htna.tistory.com/342 )
     - C와 C#통신하는 부분을 링크 해두었습니다. 위의 코드와 동일하나. 음....그대로 가따붙이니 안되네요.  조금 수정하였습니다. 


Posted by 모과이IT
,