Escribir un contenedor administrado para código no administrado (C ++) – tipos / estructuras personalizadas

faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration( faacEncHandle hEncoder); 

Estoy tratando de encontrar un envoltorio simple para esta biblioteca de C ++; Nunca he hecho más que muy simple p / invoke interop antes, como una llamada de función con argumentos primitivos.

Entonces, dada la función C ++ anterior, por ejemplo, ¿qué debo hacer para tratar con el tipo de retorno y el parámetro?

FAACAPI se define como: #define FAACAPI __stdcall

faacEncConfigurationPtr se define:

 typedef struct faacEncConfiguration { int version; char *name; char *copyright; unsigned int mpegVersion; unsigned long bitRate; unsigned int inputFormat; int shortctl; psymodellist_t *psymodellist; int channel_map[64]; } faacEncConfiguration, *faacEncConfigurationPtr; 

¿Esto significa que el tipo de retorno de la función es una referencia a esta estructura?

Y faacEncHandle es:

 typedef struct { unsigned int numChannels; unsigned long sampleRate; ... SR_INFO *srInfo; double *sampleBuff[MAX_CHANNELS]; ... double *freqBuff[MAX_CHANNELS]; double *overlapBuff[MAX_CHANNELS]; double *msSpectrum[MAX_CHANNELS]; CoderInfo coderInfo[MAX_CHANNELS]; ChannelInfo channelInfo[MAX_CHANNELS]; PsyInfo psyInfo[MAX_CHANNELS]; GlobalPsyInfo gpsyInfo; faacEncConfiguration config; psymodel_t *psymodel; /* quantizer specific config */ AACQuantCfg aacquantCfg; /* FFT Tables */ FFT_Tables fft_tables; int bitDiff; } faacEncStruct, *faacEncHandle; 

Así que dentro de esa estructura vemos muchos otros tipos … hmm.

Esencialmente, ¿estoy tratando de averiguar cómo lidiar con estos tipos en mi contenedor administrado?
¿Necesito crear versiones de estos tipos / estructuras, en C #? Algo como esto:

 [StructLayout(LayoutKind.Sequential)] struct faacEncConfiguration { uint useTns; ulong bitRate; ... } 

Si es así, ¿puede el tiempo de ejecución “mapear” automáticamente estos objetos entre sí? Y, ¿tendría que crear estos tipos “asignados” para todos los tipos en estos tipos de retorno / jerarquías de tipo de parámetro, hasta que llego a todos los primitivos?

Sé que este es un tema amplio, ¡cualquier consejo para estar al día rápidamente sobre lo que necesito aprender para que esto suceda será muy apreciado! ¡Gracias!

Estás en el camino correcto con la forma en que necesitarías crear estructuras administradas que representen estructuras sin modificar para usar con P / Invoke.

Sin embargo, no es la mejor estrategia para interoperar con bibliotecas no administradas, ya que el uso de esta API de C # sería como usar una API de C: cree e inicialice una estructura, pásela a una función y obtenga otra estructura a cambio.

Está bien usar P / Invoke para una llamada de función impar que no esté expuesta de otra manera como API .NET, pero para un envoltorio de API completo recomendaría usar C ++ administrado (C ++ / CLI). Es absolutamente incomparable en la creación de capas de interoperabilidad no administradas para .NET.

El mayor desafío sería convertir esta interfaz esencialmente en C en una interfaz orientada a objetos, en la que se eliminan los métodos de los objetos, en lugar de llamar a funciones globales con estructuras de miembros totalmente públicos.

Cuando comience a escribir gráficos de estructuras elaboradas para P / Invoke, tendría que lidiar con un poco de “magia” que gobierna cómo los tipos primitivos gestionados se convierten en tipos no gestionados. A menudo, el uso de tipos incorrectos causará un error en tiempo de ejecución.

Con C ++ administrado (IJW – It Just Works) usted define estructuras administradas, clases, interfaces en C ++, lo que permite un uso más natural de la biblioteca subyacente y una interfaz más nativa para su aplicación C #.

Este es un gran resumen de C ++ / CLI. También MSDN tiene una amplia documentación para todas las características de C ++ administradas.

Sí, deberías declarar todas estas estructuras en c #. Tenga cuidado de declarar miembros con tamaños correctos. Por ejemplo, ‘long’ es de 32 bits en C ++, pero de 64 bits en C #. Para un puntero o nulo * en C ++, use IntPtr en C #, etc.