2012-06-01 4 views
3

관리되지 않는 타사 라이브러리 (C)가 있습니다. C++/CLI에서 래퍼를 작성하려고하므로 C#에서 라이브러리를 사용할 수 있습니다. 몇 가지 C 예제가 있지만 관리되지 않는 힙과 관리되는 힙을 연결하는 방법을 알 수 없습니다.관리 대상 반환 값으로 관리되지 않는 구조체

라이브러리의 함수 중 하나가 관리되는 래퍼에 보관해야하는 구조체를 반환합니다. 이 구조체는 다른 함수의 매개 변수로 사용됩니다.

작업 C-예 :

library.h

typedef struct FOO_BAR_STRUCT* FOO_BAR; 
DLLEXPORT FOO_BAR FooBarCreate(); 

Example.c는

#include <library.h> 

int main(int argc, char* argv[]) { 
char* address = "127.0.0.1"; 
FOO_BAR fb = NULL; 

fb = FooBarCreate(); 

FooBarRegister(fb, address); 
} 

그래서 내 래퍼에, 나는 예는 무엇을 다시 시도하십시오. 구조체가있는 힙이 문제인지 알았지 만 해결 방법을 찾을 수 없었습니다.

내 C# 프로젝트에서 사용하기 위해 C++/CLI .dll로 컴파일 된 내 C++ 코드.

FooBarComm.h

#include <library.h> 

ref class FooBarComm 
{ 
public: 
    FooBarComm(char* address); 
    ~FooBarComm(); 

private: 
    FOO_BAR fb; 
}; 

FooBarComm.cpp

#include "FooBarComm.h" 

FooBarComm::FooBarComm(char* address) 
{ 
    fb = FooBarCreate(); 
    FooBarRegister(fb, address); 
} 

FooBarComm::~FooBarComm() 
{ 
} 

그리고이 실패합니다. FOO_BAR 구조체의 인스턴스를 관리되지 않는 코드에서 관리되는 클래스로 가져온 다음 나중에 함수의 인수로 사용합니다.

편집 :

I fails with a warning LNK4248: unresolved typeref token (0100000D)
error LNK2028: unresolved token (0A00000A) "extern "C" struct FOO_BAR_STRUCT
error LNK2019: unresolved external symbol "extern "C" struct FOO_BAR_STRUCT

나는 문제가 내가 라이브러리와 함께 제공되는 헤더 파일에 FOO_BAR_STRUCT의 정의를 필요가 없다는 것입니다 같아요. 나는이 도서관을 싫어하기 시작했다.

구조체에 대한 참조를 보유하는 관리되지 않는 클래스를 만든 다음이 관리되지 않는 클래스를 관리되는 클래스에서 참조하는 것이 합리적일까요?

error LNK2019: unresolved external symbol _FooBarCreate referenced

편집 :

#include <library.h> 

#pragma unmanaged  
class FooBarComm { 
... 

내가 컴파일 오류가

FooBarComm.h : 나는 "정상적인"C++ 클래스로 변경하는 경우

, 나는 다른 컴파일 오류가 2 :

물론 .lib 파일에 대한 누락 된 링크입니다.

+1

왜'fb'보다는'afapd'입니까? –

+0

복사 실수를했습니다! –

+1

질문에있는 코드가 실패한 이유를보기가 어렵습니다. 그리고 물론 당신은 실제로 그것이 어떻게 실패했는지 진술하지 않았습니다. 방금 "이 실패"라고하셨습니다. 세부 사항을 제공하지 않으면 어떻게 도움을받을 수 있습니까? 어떤 방법으로 실패합니까? 정확 해. 공급 세부 사항. –

답변

1

타사 라이브러리의 .lib 파일 누락으로 인해 링커 오류가 발생했습니다. 나는 당신이 귀하의 링크 옵션에 추가하면 문제가 해결 될 것이라고 기대합니다.

+0

이 부분을 살펴 보겠습니다. –

+1

그리고 네가 어디 있는지. –

0

byte [] 배열에 대한 명시 적 변환 사용을 고려하십시오. 이렇게하면 구조체의 위치를 ​​명시 적으로 지정할 수 있습니다.C에서

는, 당신은 : C#에서

extern "C" void FooBarCreate(FooBar* Data); 

extern "C" void FooBarUse(FooBar* Data) 

당신은 쓰기 :

[DllImport("SomeFile.dll")] 
    public static extern void FooBarCreate_DLL([In,Out] byte[] BufForFOOBAR); 

    [DllImport("SomeFile.dll")] 
    public static extern void FooBarUSE_DLL([In,Out] byte[] BufForFOOBAR); 


      /// Call DLL with managed struct 
    public static Int32 FooBarUse_Managed(ManagedFooBar Value) 
    { 
     byte[] ValueBuffer = StructureToByteArray(Value); 

     return FooBarUse_DLL(ValueBuffer); 
    } 

      /// Get value from native DLL to managed struct 
    public static void FooBarCreate_Managed(ref ManagedFooBar Value) 
    { 
     byte[] ValueBuffer = new byte[Marshal.SizeOf(Value)]; 

     FooBarCreate_DLL(ValueBuffer); 

     object TmpObj = new ManagedFooBar(); 

     ByteArrayToStructure(ValueBuffer, ref TmpObj); 

     Value = (ManagedFooBar)TmpObj; 
    } 

네이티브 함수는 C 번호로 직접 호출됩니다.

StructToByteArray 및 ByteArrayToStruct 기능은 바로 여기에 있습니다 :

using System.Runtime.InteropServices; 
using System.Runtime.Serialization; 


    public static byte[] StructureToByteArray(object obj) 
    { 
     int len = Marshal.SizeOf(obj); 

     byte[] arr = new byte[len]; 

     IntPtr ptr = Marshal.AllocHGlobal(len); 

     Marshal.StructureToPtr(obj, ptr, true); 

     Marshal.Copy(ptr, arr, 0, len); 

     Marshal.FreeHGlobal(ptr); 

     return arr; 
    } 

    public static void ByteArrayToStructure(byte[] bytearray, ref object obj) 
    { 
     int len = Marshal.SizeOf(obj); 

     IntPtr i = Marshal.AllocHGlobal(len); 

     Marshal.Copy(bytearray, 0, i, len); 

     obj = Marshal.PtrToStructure(i, obj.GetType()); 

     Marshal.FreeHGlobal(i); 
    } 

마지막으로 한가지, (C#의 경우) FooBarManaged :

[Serializable] 
    /// Sequential - make sure C does uses the same struct member alignment 
[StructLayout(LayoutKind.Sequential, Pack=1)] 
public struct FooBarManaged 
{ 
    // Ususal POD field 
    public Int32 ExpID; 

    // Constant-sized string 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] 
    public byte[] FileName; 
} 

이 코드에 대해 말할 정도가 아니다. 필자는 이러한 유형의 마샬링에 간단한 자동 생성기를 사용하여 기본 sqlite3 백엔드를 데이터 저장소로 사용했습니다. 따라서 C와 함께 많은 구조체를 마샬링해야 할 필요가 있습니다.

+0

나는 당신의 제안을 이해하고 있는지 잘 모르겠다. 수정할 수없는 제 3 자 라이브러리가 있습니다. 헤더 파일, .dll 및 .obj 파일을 사용할 수 있습니다. 먼저 두 개의 함수를 사용하여 C 래퍼를 만드는 것이 좋습니다. 나는 일반적인 "최선의 방법"이 C++/CLI 래퍼를 사용하는 것이라고 생각했다. –

+0

예, 귀하의 (또는 제안 된) 스타일을 지원하기 위해 해당 라이브러리를 래핑하는 것은 옵션입니다. 그건 물론 제 3 자 lib의 크기에 달려 있습니다. 제 경우에는 두 부분을 담당했습니다. –

+0

이것은 나에게 가짜 보입니다. –

관련 문제