2011-09-11 12 views
5

Tengo una biblioteca no administrada que expone algunas interfaces. Los usuarios pueden implementar interfaces y pegarlas en la biblioteca con su implementación personalizada.Envoltura administrada con interfaz no administrada

Me gustaría proporcionar un contenedor administrado para esta biblioteca. Envolver una interfaz no administrada con una administrada es fácil. Pero en mi caso me gustaría apoyar implementaciones de usuario de varias interfaces, lo que significa que necesito tomar una implementación administrada de una interfaz y envolverla usando su contraparte no administrada antes de enviarla a las profundidades de la parte no administrada de la biblioteca.

he intentado algo así como:

class UnmanagedWrapper { 
DoSomething() {m_clr.DoSomething();} 
IManaged^ m_clr; 
} 

pero no puedo han logrado los miembros dentro de una clase no administrada, el compilador legítimamente reclama.

¿Puedo hacer algo aquí?

+1

Contexto insuficiente. Utilice gcroot <> o Marshal :: GetFunctionPointerForDelegate(). –

Respuesta

0

Aquí hay información relacionada para las soluciones cuando una biblioteca no está administrada y un lenguaje administrado usa esas bibliotecas.

El contexto de esta información es una manera de utilizar GoogleTest en Visual Studio:

Getting started with Google C++ Testing Framework

Nota importante para Visual C++ usuarios Si coloca sus pruebas en una biblioteca y su principal() la función está en una biblioteca diferente o en su archivo .exe , esas pruebas no se ejecutarán. La razón es un error en Visual C++. Cuando define sus pruebas, Google Test crea ciertos objetos estáticos para registrarlos. Estos objetos no están referenciados desde en otro lugar, pero se supone que todavía se deben ejecutar sus constructores. Cuando El vinculador de Visual C++ ve que no se hace referencia a nada en la biblioteca desde en otros lugares tira la biblioteca. Debe hacer referencia a su biblioteca con las pruebas de su programa principal para evitar que el enlazador lo descarte. Aquí es cómo hacerlo. En algún lugar de su código de biblioteca declarar una función:

__declspec (dllexport) int PullInMyLibrary() { return 0; }

Si coloca sus pruebas en una biblioteca estática (no DLL) y luego __declspec (dllexport) es

No es necesario. Ahora, en su programa principal, escribir un código que invoca que funcionan:

int PullInMyLibrary(); 
    static int dummy = PullInMyLibrary(); 

Esto mantener sus pruebas de referencia y hará que se registran en inicio.

Además, si define sus pruebas en una biblioteca estática, agregue /OPT: NOREF a las opciones del enlazador de programa principal. Si usa MSVC++ IDE, vaya a las propiedades del proyecto .exe/Configuración Propiedades/Enlazador/Optimización y establezca Referencias para Mantener Datos no referenciados (/ OPT: NOREF). Esto mantendrá al enlazador de Visual C++ desde descartando los símbolos individuales generados por las pruebas desde el ejecutable final .

Hay una trampa más, sin embargo. Si utiliza Google Test como una biblioteca estática (así es como se define en gtest.vcproj) sus pruebas deben también residen en una biblioteca estática. Si tiene que tenerlos en una DLL, , debe cambiar Google Test para incorporar también una DLL. De lo contrario, sus pruebas no se ejecutarán correctamente o no se ejecutarán en absoluto. La conclusión general de aquí es: haga su vida más fácil: ¡no escriba sus pruebas en las bibliotecas !

0

Tal gcroot<> es lo que quiere:

class UnmanagedWrapper { 
    DoSomething() {m_clr.DoSomething();} 
    gcroot<IManaged^> m_clr; 
} 
0

debe importar el archivo DLL no administrado en su aplicación C# .Net. Mi ejemplo devuelve un puntero a una estructura pero puede proporcionar cualquier otro tipo de devolución que su aplicación necesite. Asegúrese de usar dumpbin.exe/EXPORTS para obtener el nombre completo de la función/EntryPoint del dll. Aquí está toda mi clase:

entorno
using System; 
using System.Runtime.InteropServices; 

namespace aviationLib 
{ 
    public struct MAGtype_GeoMagneticElements 
    { 
     public double Decl; /* 1. Angle between the magnetic field vector and true north, positive east*/ 
     public double Incl; /*2. Angle between the magnetic field vector and the horizontal plane, positive down*/ 
     public double F; /*3. Magnetic Field Strength*/ 
     public double H; /*4. Horizontal Magnetic Field Strength*/ 
     public double X; /*5. Northern component of the magnetic field vector*/ 
     public double Y; /*6. Eastern component of the magnetic field vector*/ 
     public double Z; /*7. Downward component of the magnetic field vector*/ 
     public double GV; /*8. The Grid Variation*/ 
     public double Decldot; /*9. Yearly Rate of change in declination*/ 
     public double Incldot; /*10. Yearly Rate of change in inclination*/ 
     public double Fdot; /*11. Yearly rate of change in Magnetic field strength*/ 
     public double Hdot; /*12. Yearly rate of change in horizontal field strength*/ 
     public double Xdot; /*13. Yearly rate of change in the northern component*/ 
     public double Ydot; /*14. Yearly rate of change in the eastern component*/ 
     public double Zdot; /*15. Yearly rate of change in the downward component*/ 
     public double GVdot; /*16. Yearly rate of change in grid variation*/ 
    }; 

    public class Declination 
    { 
     [DllImport("wmm.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "[email protected]@[email protected]@[email protected]")] 
     public static extern IntPtr GeoMagneticElements(float sdate, int igdgc, int units, float alt, float latitude, float longitude); 

     public MAGtype_GeoMagneticElements e; 

     public MAGtype_GeoMagneticElements MagDeclination(float decimalLat, float decimalLon) 
     { 

      try 
      { 
       String d = DateTime.Now.Year.ToString("D4") + '.' + DateTime.Now.Day.ToString("D1"); 
       IntPtr pnt = GeoMagneticElements((float)Convert.ToDouble(d), 1, 3, 3000.0f, decimalLat, decimalLon); 
       e = Marshal.PtrToStructure<MAGtype_GeoMagneticElements>(pnt); 
      } 
      catch (System.EntryPointNotFoundException se) 
      { 
       Console.WriteLine(se.Message); 
      } 

      return e; 
     } 
    } 
} 

La palabra tiene que ser la misma tanto para el administrado y no administrado de modo que si el archivo DLL de 32 bits es entonces el .NET tiene que ser así.

Cuestiones relacionadas