2015-04-17 3 views
0

Я хочу создать класс C++, который обертывает ссылку на управляемый объект, существующий в приложении форм выигрышей, чтобы с ним можно было манипулировать с обеих сторон (C# и C++).Обратный pinvoke, вызов метода объекта C# из родной C/C++ DLL без CLI/CLR

Этот объект будет доступен асинхронно с C++. Для этого я хотел бы сохранить ссылку на этот управляемый объект в собственном коде. Я знаю, что GC может его собрать, поэтому я прочитал, что я должен ссылаться на него где-то в управляемом коде, чтобы предотвратить это.

Мой вопрос: возможно ли хранить ссылку на управляемый объект в родной DLL (без использования материалов CLI/CLR) и использовать его для асинхронного вызова методов? И если да, то каков синтаксис для передачи объекта? Также как насчет методов этого управляемого объекта? Нужно ли мне также хранить ссылку на них в моем родном коде?

спасибо. :)

+0

COM является чистым способом осуществить это –

+0

* Мой вопрос: можно ли сохранить ссылку на управляемый объект в родной DLL (без использования CLI/CLR) * На некотором уровне вы должны сообщить CLR, что вы не хотите, чтобы объект был собран. Вы можете сохранить ссылку в статическом свойстве, вы можете напрямую связать ее с GCHandle, вы можете использовать COM, но, правда, вам нужно сообщить CLR. – xanatos

+0

Не является ли CLR своего рода расширением C++? Является ли это частью C#? Без CLI/CLR я подразумевал, что хочу использовать стандартный C++, а не расширенный C++ MS. – Virus721

ответ

0

Я пишу это в надежде на то, что Дэвид Heffernan исправит меня и научи меня что-то :-)

Как я уже писал в комментариях:

Мой вопрос состоит в : возможно ли хранить ссылку на управляемый объект в родной DLL (без использования CLI/CLR)

На некотором уровне вы должны сообщить CLR, что вы не хотите, чтобы объект был собран , Вы можете сохранить ссылку в статическом свойстве, вы можете напрямую связать ее с GCHandle, вы можете использовать COM, но, правда, вам нужно сообщить CLR.

Использование COM-объектов является сложным (по крайней мере, для меня :-)).

Что бы я сделал:

Учитывая MyClass, с объектом, созданным C# -side с DoSomething метод, который я хочу использовать как C# и C++ сторону.

public class MyClass 
{ 
    public string Name; 
    public string Surname; 

    public bool DoSomething(int value1, int value2) 
    { 
     return Name.Length == value1 || Surname.Length == value2; 
    } 
} 

Я хотел бы создать MyProxyClass вроде этого:

public class MyProxyClass 
{ 
    private delegate void FreeMeDelegate(); 

    [return:MarshalAs(UnmanagedType.I1)] 
    private delegate bool DoSomethingDelegate(int value1, int value2); 

    private GCHandle Handle; 
    private DoSomethingDelegate DoSomething { get; set; } 

    // You pass this function pointer to C++. Its signature is: 
    // bool(__stdcall *DoSomething)(int32_t, int32_t) 
    public IntPtr DoSomethingPtr { get; private set; } 

    private FreeMeDelegate FreeMe { get; set; } 

    // You have to pass this function too to C++. C++ code must use it 
    // to free MyProxyClass. Its signature is: 
    // void (__stdcall *FreeMe)(void) 
    public IntPtr FreeMePtr { get; private set; } 

    public void FreeMeImpl() 
    { 
     if (Handle.IsAllocated) 
     { 
      Handle.Free(); 
      DoSomething = null; 
      DoSomethingPtr = IntPtr.Zero; 
      FreeMe = null; 
      FreeMePtr = IntPtr.Zero; 
     } 
    } 

    public MyProxyClass(MyClass obj) 
    { 
     Handle = GCHandle.Alloc(this, GCHandleType.Normal); 

     // This will implicitly create a reference to obj. GC can't 
     // collect MyProxyClass because we have a GCHandle on it, 
     // and can't collect obj because there is a delegate that 
     // has a reference on it. 
     DoSomething = obj.DoSomething; 
     DoSomethingPtr = Marshal.GetFunctionPointerForDelegate(DoSomething); 

     FreeMe = FreeMeImpl; 
     FreeMePtr = Marshal.GetFunctionPointerForDelegate(FreeMe); 
    } 
} 

Этот класс при создании автоматически останавливает GC собирать ее. Затем создает делегатов методу DoSomething и к методу FreeMe, который должен использовать код C++ для его освобождения.

Теперь, C# -side:

MyClass myclass = ...; // you instance of myclass 

var proxy = new MyProxyClass(myclass); 

// Now you pass these to C++ 
//proxy.DoSomethingPtr; 
//proxy.FreeMePtr; 
+0

Это все на моей голове.Я, я бы использовал COM, или смешанный режим C++/CLI, или UnmanagedExports. –

Смежные вопросы