2009-06-10 3 views
0

요약 :복잡의 PInvoke 상황 - 함수 오버로딩을 피하기

내가 C 번호에서 전화가 C 함수의 무리가 있습니다. 내 현재 작업 솔루션은 함수 오버로딩을 기반으로하고 더 우아한 솔루션이 있는지 궁금하네요.

ㄴ 재료 :

어딘가에 헤더 파일

typedef struct _unknown_stuff * handle; // a opaque pointer 

함수 C에서

func(uint  num_entries, 
     handle * objects, 
     uint * n) 
{ ... } 

예에서

기능이 유사한 표기 :

// warning: i bet that the syntax is not correct but you should get the idea... 

uint n; 

func(0, null, &n); 

handle * objects = malloc(n * sizeof(handle)); 

func(n, objects, null); 

는 C# 물건 : 오른쪽

지금은 C#으로 다음과 같은 일을 해요 : 다음

public struct handle 
{ 
    public IntPtr Pointer; 
} 

// version to get number of objects 
[DllImport(dll, ...] 
private static extern void 
func( uint  must_be_zero, 
     object  must_be_null, 
     out uint n); 

// version to get the actual data 
[DllImport(dll, ...] 
private static extern void 
func( uint   num_entries, 
     [Out] handle[] objects, 
     int   must_be_zero); 

과 :

handle[] objects; 

uint n = 42; 

func(0, null, out n); 

objects = new handle[n]; 

func(n, objects, 0); 

[질문

이후 저는 C# 멍청한 놈입니다. 이것이 최선의 방법인지 궁금 해서요. 이 작업을 수행. 특히 함수 오버로딩에 대한 방법이 있는지 알고 싶습니다.

답변

1

우선 두 번째 C# 서명에서 세 번째 인수가 int이고 해당 C 인수가 여전히 int*인데 비해 코드가 잘못되었습니다. sizeof(int)==sizeof(int*)이 있기 때문에 32 비트 Windows를 대상으로 할 때 작동합니다. 0을 전달하면 int 포인터를 전달하지만 64 비트는 안전하지 않습니다. 그런 식으로하고 싶다면 IntPtr을 사용해야합니다.

과는 별도로

, 당신은 시도 할 수 :

[DllImport(dll, ...] 
private static extern void func(
    uint num_entries, 
    [Out] handle[] objects, 
    [Out] int[] num_devices); 

을 세 번째 인수를 배열을 만드는 당신이 널 (null)이 통과 할 수 있도록.

또는 포인터 만 사용하십시오. 그것에 대해 나쁜 점은 없으며 unsafe 키워드를 두려워하지 마십시오. P/Invoke는 본질적으로 안전하지 않으므로 이에 대해 명시 할 수도 있습니다.

+0

좋아, 이제 좀 당황 스럽다. C#이 포인터를 지원한다는 것을 몰랐다. 포인터를 사용하면 힌트를 주셔서 감사합니다 :) 도서관에서 벗어나 C# 서적을 찾으십시오. –

0

C DLL은 0으로 보지 않을 것인가? null로 처리할까요?

하나의 기능 만 있습니다. 맞습니까? 즉, C 함수는 null case에 대해 별도로 정의되지 않고 한 번 정의되며 거기에

if(objects == NULL)
수표가있을 것입니다. 대부분의 시스템에서 (대상 시스템의 stdio.h를 확인하십시오.) 이것은 0입니다. 그래서이 위치에서 0 값을 사용하여 pinvoke를 호출하면 오버로드 할 작업을 수행해야합니다.

+0

그래, 맞아.하지만 형식 변환에 심각한 문제가있어 그 방법을 과부하하기로 결정했습니다. –

+0

그가 첫 번째 C# 서명 (세 번째 인수가 'out'인 경우)을 사용하면 0을 전달하면 도움이되지 않습니다. 변수를 선언하고 0을 할당 한 다음 'out'으로 전달해야합니다. 그러면 C 함수는 실제로 그 변수의 주소를 0으로 얻습니다. 두 번째 서명을 사용하면 0을 전달할 수 있지만 (위의 설명은 이미 잘못되었지만 위의 설명은 잘못되었지만) 값을 사용해야하는 경우에는 실제 int 변수를 전달할 수 없습니다 검색 됨. –