... | ... | @@ -7,17 +7,17 @@ |
|
|
> System.Runtime.InteropServices
|
|
|
|
|
|
```
|
|
|
[DllImport("example.dll", EntryPoint = "example_printInfo", CallingConvention = CallingConvention.Cdecl)]
|
|
|
[DllImport("example.dll", EntryPoint = "printInfo", CallingConvention = CallingConvention.Cdecl)]
|
|
|
static extern void printInfo();
|
|
|
```
|
|
|
* **DllImport()**에 DLL 파일명을 지정하고 `static`과 `extern` 키워드를 사용하여 Method를 정의한다.
|
|
|
* **EntryPoint** : DLL에 포함된 Method를 지정하면 다른 이름으로 Method를 정의할 수 있다.
|
|
|
* **CallingConvention** : Method를 호출하는 데 필요한 규칙을 지정한다. (CallingConvention.Cdecl : 매개변수 사용을 허용)
|
|
|
* **DllImport()**에 DLL 파일명과 속성을 지정하고 `static`과 `extern` 키워드를 사용하여 Method를 정의한다.
|
|
|
* **EntryPoint** : DLL에 포함된 Method 중 호출할 Method의 이름을 지정한다. 이 속성을 생략할 경우 Method의 이름을 그래도 사용하고, 속성을 사용하면 다른 이름으로 Method를 사용할 수 있다.
|
|
|
* **CallingConvention** : Method를 호출할 때 매개변수를 전달하는 방식이나 Method를 호출한 뒤 Stack Frame 정리에 관한 규칙을 지정한다.
|
|
|
|
|
|
---
|
|
|
#### **예제**
|
|
|
|
|
|
```
|
|
|
// example.dll 내용
|
|
|
// example.dll
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
... | ... | @@ -67,6 +67,54 @@ Area : 15 |
|
|
### **Marshaling**
|
|
|
**Marshaling**은 한 언어로 작성된 프로그램의 표현방식을 다른 언어에 적합하게 다른 형식으로 변환하는 과정을 말한다.
|
|
|
|
|
|
* MarshalAs을 사용하여 Method의 매개변수나 반환 값을 **Marshaling**할 수 있다.
|
|
|
|
|
|
```
|
|
|
[DllImport("example.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
[return: MarshalAs(UnmanagedType.I4)]
|
|
|
static extern int stringLength(
|
|
|
[MarshalAs(UnmanagedType.LPStr)]
|
|
|
string str);
|
|
|
```
|
|
|
|
|
|
* Unmanaged Method에서 사용되는 구조체 및 클래스의 Field를 **Marshaling**할 수 있다.
|
|
|
|
|
|
```
|
|
|
// example.dll
|
|
|
|
|
|
typedef struct Data
|
|
|
{
|
|
|
char name[10];
|
|
|
int value[5];
|
|
|
int count;
|
|
|
} Data;
|
|
|
```
|
|
|
```
|
|
|
// C#
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
public struct Data
|
|
|
{
|
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
|
|
|
public string name;
|
|
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
|
|
|
public int[] value;
|
|
|
|
|
|
public int count;
|
|
|
}
|
|
|
|
|
|
[DllImport("Win32Project1.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
|
static extern void checkData(Data data);
|
|
|
|
|
|
static void Main()
|
|
|
{
|
|
|
Data data = new Data();
|
|
|
/* 생략 */
|
|
|
checkData(data);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### **Marshal Method**
|
|
|
| **멤버** | **설명** |
|
|
|
| -------- | -------- |
|
... | ... | @@ -77,7 +125,7 @@ Area : 15 |
|
|
| Marshal.Copy() | Unmanaged 메모리의 Pointer를 Managed 형식의 배열에 또는 그 반대로 값을 복사 |
|
|
|
| Marshal.SizeOf() | Unmanaged 형식의 변수 크기를 byte 단위로 반환 |
|
|
|
|
|
|
#### **예시**
|
|
|
#### **예제**
|
|
|
|
|
|
```
|
|
|
int intSize = 4;
|
... | ... | @@ -124,7 +172,8 @@ public static string StringFromUtf8Ptr(IntPtr ptr) // ptr is null-terminated |
|
|
```
|
|
|
* `IntPtr`은 Pointer를 나타내는 형식이다. 매개변수를 `IntPtr` 형식인 ptr로 받는다.
|
|
|
* ptr을 `byte` 단위로 읽어서 0이 되기 전까지 len을 증가시켜 문자열의 길이를 구한다.
|
|
|
* Managed byte 배열에 Unmanaged Pointer 변수에 저장된 값을 지정한 길이만큼 복사한다.
|
|
|
* Unmanaged Pointer(ptr)의 값을 Managed byte 배열(array)에 지정한 길이만큼 복사한다.
|
|
|
* ptr에 저장된 UTF-8 방식의 문자열을 byte 배열인 array에 저장한 것이다. 이 문자열을 string 형식으로 Encoding 후 반환한다.
|
|
|
|
|
|
### **U8Conv.Utf8BytesFromString()**
|
|
|
```
|
... | ... | @@ -136,8 +185,9 @@ public static byte[] Utf8BytesFromString(string s) |
|
|
return buf;
|
|
|
}
|
|
|
```
|
|
|
* 문자열 길이에 따라 UTF-8 방식으로 Encoding하여 나올 수 있는 최대 크기를 cnt에 저장한다.
|
|
|
* Unmanaged 문자열은 배열의 끝 요소에 0('\0')이 저장되어야 하므로 cnt보다 1 증가한 크기의 byte 배열인 buf를 생성한다.
|
|
|
* string 형식의 변수 s를 byte로 Encoding하여 buf에 저장한 후 반환한다.
|
|
|
* string 형식의 s 변수를 UTF-8 방식으로 Encoding한 후 byte 배열인 buf에 저장하여 반환한다.
|
|
|
|
|
|
### **Kai.DisplayStr()**
|
|
|
```
|
... | ... | @@ -160,8 +210,8 @@ try |
|
|
}
|
|
|
```
|
|
|
* Unmanaged 메모리에 bufsize+1 크기만큼의 buf를 할당한다.
|
|
|
* 해당 kai ID(id)의 데이터를 string으로 buffer(buf)에 표시한다.
|
|
|
* buf를 U8Conv.StringFromUtf8Ptr()에 매개변수로 넘긴 후 string 형식으로 반환한다.
|
|
|
* kai_display_str()에서는 해당 kai ID(id)의 데이터를 buf에 저장한다.
|
|
|
* buf에 저장된 문자열은 UTF-8 방식이므로 U8Conv.StringFromUtf8Ptr()을 사용해 string 형식으로 변환 후 반환한다.
|
|
|
|
|
|
---
|
|
|
|
... | ... | @@ -190,9 +240,9 @@ public static string CellByName(int id, string col_name, int row) |
|
|
return U8Conv.StringFromUtf8Ptr(ptr);
|
|
|
}
|
|
|
```
|
|
|
* string 형식의 col_name을 U8Conv.Utf8BytesFromString()의 매개변수로 넘긴 후 byte 배열로 반환하여 col에 저장한다.
|
|
|
* string 형식의 col_name을 U8Conv.Utf8BytesFromString()에서 UTF-8 방식으로 Encoding한 후 byte 배열로 반환하여 col에 저장한다.
|
|
|
* kai_cell_byname()를 사용하여 해당 Kai ID(id)에서 byte 배열(col)의 row 번째 내용을 반환하여 ptr에 저장한다.
|
|
|
* ptr은 Unmanaged Pointer이므로 IntPtr 형식으로 저장되어 있을 것이다. 이를 U8Conv.StringFromUtf8Ptr()의 매개변수로 넘긴 후 string 형식으로 반환한다.
|
|
|
* ptr에 저장된 문자열은 UTF-8 방식이므로 U8Conv.StringFromUtf8Ptr()을 사용해 string 형식으로 변환 후 반환한다.
|
|
|
|
|
|
### **Kai.row_howmany()**
|
|
|
```
|
... | ... | @@ -252,6 +302,6 @@ int metic_init(char *server_ip, unsigned short server_port, int init_conn_try_ti |
|
|
void (*conn_cb)(enum metic_status status, int sv_info_kai),
|
|
|
void (*login_rsp_cb)(int success, int info_kai)) { /* 내용 */ }
|
|
|
```
|
|
|
* metic_init() 매개변수로 받은 정보를 이용해 metic을 초기화하는 Method이다. 정상적으로 연결되면 1을 반환하고, 실패하면 0을 반환한다.
|
|
|
* 매개변수에서 char 형식의 Pointer로 선언된 server_ip는 C#에서 string 형식으로 대체할 수 있다. 또한, unsigned short 형식의 server_port도 ushourt로 대체하여 사용한다.
|
|
|
* metic_init() 매개변수로 받은 정보를 이용해 metic을 초기화하는 Method이다.
|
|
|
* 매개변수에서 char 형식의 Pointer로 선언된 server_ip는 C#에서 string 형식으로 대체할 수 있다. 또한, unsigned short 형식의 server_port도 ushort로 대체하여 사용한다.
|
|
|
* Function Pointer로 선언된 conn_cb와 login_rsp_cb는 Delegate로 선언된 Connection과 LoginRsp로 대체하여 사용한다. 이와 같은 형식의 Method를 매개변수로 받아서 사용할 수 있다. |
|
|
\ No newline at end of file |