이번 절의 fixed는 이전 절의 예약어와 이름은 같지만 그 용도는 다르다. 이 구문을 이해하기
위해서는 C/C++ 지식이 요구된다. 가령 다음과 같은 C++ 구조체가 있을때,
// C/C++로 정의한 구조체
struct CppStructType
{
public :
int fields[2];
__int64 dummy[3];
};
이것을 인자로 받아들이는 C++ DLL 함수가 있다고 가정해 보자.
// C/C++로 정의한 함수
__declspec(dllexport) void __stdcall ProcessItem(CppStructType *value)
{
for (int i = 0; i < 2; i++)
{
value->fields[i] = (i + 1) * 2;
}
for (int i = 0; i < 3; i++)
{
value->dummy[i] = (i + 1) * 20;
}
}
위의 C++ 함수를 extern 예약어를 통해 C#에서 호출하려면 우선 CppStructType에 맞는 구조체를
정의해야 한다. 그런데 이 구조체를 다음과 같이 정의할 수 있을까?
// C#의 struct
struct CSharpStructType
{
public int[] fields;
public long[] dummy;
}
static void Main(string[] args)
{
CSharpStructType item = new CSharpStructType();
item.fields = new int[2];
item.dummy = new long[3];
}
CppStructType과 CSharpStructType이 어떻게 메모리에 할당되는지 살펴보면 그 답을 알 수 있다.
CppStructType의 메모리 할당이 연속적인 반면, C#의 경우 필드마다 배열이 다시 참조 객체이므로
별도의 메모리를 할당받고 CSharpStructType의 필드는 그에 대한 참조 주소를 갖는 형식으로
할당된다. 따라서 C++의 ProcessItem 함수를 다음과 같이 호출하면,
struct CSharpStructType
{
public int[] fields;
public long[] dummy;
}
class Program
{
[DllImport("...C/C++ processItem 구현.dll...")]
internal static unsafe extern int ProcessItem(CSharpStructType value);
unsafe static void Main(string[] args)
{
CSharpStructType item = new CSharpStructType();
item.fields = new int[10];
item.dummy = new long[20];
ProcessItem(item); // 프로세스 비정상 종료
}
}
C++ DLL 측에서 참조 오류 예외가 발생하면서 프로그램이 비정상 종료되게 된다. 이런 문제를 해결