2016-08-10 2 views
1

이 C 코드를 C#의 래퍼 클래스에서 사용하고 싶습니다. 구조체와 함수 포인터를 포함하여 다양한 매개 변수로 strucutre 있습니다.구조체를 포함하는 마샬링/핀볼킹 함수 포인터

C 코드 :

struct wiringPiNodeStruct 
{ 
    int  pinBase ; 
    int  pinMax ; 

    int   fd ; // Node specific 
    unsigned int data0 ; // ditto 

    void (*pinMode)   (struct wiringPiNodeStruct *node, int pin, int mode) ; 

    struct wiringPiNodeStruct *next ; 
} ; 

나는 위의 코드를 정렬 화를 시도했다. 하지만 구조체 및 구조체 내의 구조체를 포함하는 함수 포인터에 대한 적절한 솔루션을 찾을 수 없습니다.

C# 코드 :

[StructLayout(LayoutKind.Sequential)] 
public struct wiringPiNodeStruct 
{ 
    public int pinBase; 
    public int pinMax; 

    public int fd; // Node specific 
    public uint data0; // ditto 


    public delegate void pinMode (struct wiringPiNodeStruct IntPtr node, int pin, int mode) ; 

    public struct wiringPiNodeStruct *next ; 
}; 
그것은 중요하지 않습니다
+0

연결된 목록은 까다 롭습니다. p/invoke에서 고통의 세계가 될 것입니다. 물론 우리는 당신의 문제가 무엇인지 전혀 몰랐습니다. 당신은 매니저에서 관리되지 않는 방법으로, 또는 다른 방법으로 마샬링하고 있습니다. 관리 코드에서이 링크 된 목록을 채우는 방법을 알지 못합니다. 또는 관리되지 않는 코드로 채워진 목록을 처리하는 방법을 알지 못합니다. 현실적으로 C++/CLI에서이 작업을 훨씬 쉽게 할 수 있습니다. 자, 너를위한 질문. 이 질문을 무시하지 마십시오. C 또는 C++로 연결된 목록을 코딩 한 적이 있습니까? 네가 안다면 희망이 거의 없기 때문에 내가 묻는다. 걷기 전에 뛰지 마십시오. –

+0

저는 C#을 처음 접했습니다. 관리 및 마샬링이라는 용어도 새로운 것입니다. 이 구조체를 사용하는 fucntions 용 C#에서 래퍼 클래스를 생성합니다. 위의 구조를 C#에서 사용하고 싶습니다. 즉에있는 구조체를 다시 만들고 싶습니다.그물 쪽과 다음 마샬링 손잡이. NET과 C 사이의 메모리를 변환하자. 아니요, 연결된 목록을 코딩하지 않았습니다. –

+0

그건 다소 힘든 일입니다. 나는 당신의 경험 수준을 감안할 때 이러한 발전된 것을 시도하는 것이 생산적이지는 않을 것이라고 생각합니다. 만약 내가 당신의 상사라면 C++에 예제 코드를 작성하여이 라이브러리에 대한 느낌과 링크 된 목록으로 작업하는 방법을 얻는 것이 좋습니다. 링크 된 목록은 이전에 본 적이 없다면 매우 까다 롭습니다. 그리고 p/invoke의 복잡성으로 그들을 배우려고 시도하는 것은 내 생각에 전혀 생산적이지 않습니다. 그런 식으로 시간 낭비 할 것입니다. –

답변

0

, 당신은 연결 사용 여부를 나열하기 전에, 또는하지 ... 당신이 여기에있는 것은 "후계자"를 키우면 가리키는 필드를 가진 단지 구조 . 물론, 제안 할 솔루션이 수정없이 작동 할 것이라고 보장 할 수는 없습니다. 그러나 나는 P/Invoke와 함께 많은 일을 해왔습니다. 그래서 그런 식으로 시도 할 것입니다 ... 적어도, 그것은 여러분에게 좋은 생각을 줄 것입니다.

간단하게 (그리고 마샬링 마술을 꺼내기 위해) 나는 pinModenextIntPtr 필드로 선언 할 것이다. IntPtr의 크기는 32 비트와 64 비트가 다릅니다. ... 관리 및 관리되지 않는 부분이 동일한 비트 수를 사용하고 있는지 확인

delegate void pinMode (IntPtr node, int pin, int mode); 

[StructLayout(LayoutKind.Sequential)] 
internal struct wiringPiNodeStruct 
{ 
    public int pinBase; 
    public int pinMax; 
    public int fd; 
    public uint data0; 
    public IntPtr pinMode; 
    public IntPtr next 
}; 

당신은 두 가지 시나리오에 직면 할 수있다; 구조체를 읽고 처리해야하거나 비 관리 형 코드를 만들고 전달해야합니다. 독서 부분을 보겠습니다. 목록을 반복하는 것은 그렇게 볼 수 있었다 ...

wiringPiNodeStruct node = ... 
while (node.next != IntPtr.Zero) 
{ 
    wiringPiNodeStruct next; 
    next = (wiringPiNodeStruct) Marshal.PtrToStructure(
     node.next, 
     typeof(wiringPiNodeStruct)); 

    ... 

    node = next; 
} 

을 당신이 pinMode 함수를 호출/필요를 원하는 경우에, 당신이 그런 일을 시도 할 수 ...

wiringPiNodeStruct node = ... 
wiringPiNodeStruct next = (wiringPiNodeStruct) Marshal.PtrToStructure(
    node.next, 
    typeof(wiringPiNodeStruct)); 

pinMode func = (pinMode) Marshal.GetDelegateForFunctionPointer(
    next.pinMode, 
    typeof(pinMode)); 

func(node.next, 0, 0); 

것은 이제 let's가 만든 구조; 물론 이것은 매우 간단한 예입니다 ... 열거 형 데이터 소스에서 링크 된 목록 구조를 생성 할 수있는 도우미 유틸리티를 만들 수 있으며 할당 된 메모리를 추적하고 더 이상 필요하지 않을 경우 관리되지 않는 메모리를 올바르게 릴리스 할 수 있습니다. pinMode가 관리되지 않는 부분에 의해 콜백으로 사용되는 경우

var second = new wiringPiNodeStruct { }; 

int size = Marshal.SizeOf(typeof(wiringPiNodeStruct)); 
IntPtr pSecond = Marshal.AllocHGlobal(size); 
Marshal.StructureToPtr(second, pSecond, true); 

pinMode func = new pinMode((ptr, pin, mode) => { }); 

var first = new wiringPiNodeStruct { }; 
first.pinMode = Marshal.GetFunctionPointerForDelegate(func); 
first.next = pSecond; 

funcpinMode 필드에 저장되어있는 포인터와 같은 수명을 가지고 있는지 확인하십시오.

wiringPiNodeStruct 유형의 다른 선언으로 재생할 수도 있습니다. 때때로 읽기 또는 쓰기에 적합한 선언을하는 것이 더 쉽습니다 ...

관련 문제