Написание управляемой оболочки для неуправляемого (C ++) кода - пользовательские типы / структуры - PullRequest
4 голосов
/ 31 мая 2010
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(
       faacEncHandle hEncoder);

Я пытаюсь найти простую оболочку для этой библиотеки C ++; Я никогда раньше не делал ничего, кроме очень простого взаимодействия p / invoke - например, один вызов функции с примитивными аргументами.

Итак, учитывая приведенную выше функцию C ++, например, что мне делать, чтобы иметь дело с типом возвращаемого значения и параметром?

FAACAPI определяется как: #define FAACAPI __stdcall

faacEncConfigurationPtr определен:

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;

AFAIK это означает, что возвращаемый тип функции является ссылкой на эту структуру?

И faacEncHandle это:

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;

Итак, внутри этой структуры мы видим много других типов ... хм.

По сути, я пытаюсь выяснить, как бороться с этими типами в моей управляемой оболочке?
Нужно ли создавать версии этих типов / структур в C #? Примерно так:

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

Если это так, то может ли среда выполнения автоматически "сопоставлять" эти объекты друг с другом? И нужно ли мне создавать эти «сопоставленные» типы для всех типов в этих возвращаемых типах / иерархиях типов параметров, вплоть до тех пор, пока я не доберусь до всех примитивов?

Я знаю, что это широкая тема, и любые советы о том, как быстро освоить то, что мне нужно, чтобы это произошло, были бы очень благодарны! Спасибо!

Ответы [ 2 ]

4 голосов
/ 31 мая 2010

Вы на правильном пути к тому, как вам нужно было бы создавать управляемые структуры, представляющие неуправляемые структуры для использования с P / Invoke.

Однако это не лучшая стратегия для взаимодействия с неуправляемыми библиотеками, потому что использование этого API из C # все равно будет похоже на использование C API - создать и инициализировать структуру, передать ее функции и получить некоторую другую структуру взамен.

Можно использовать P / Invoke для нечетного вызова функции, который иначе не раскрывается как .NET API, но для полнофункциональной оболочки API я бы настоятельно рекомендовал использовать управляемый C ++ (C ++ / CLI). Он абсолютно не имеет аналогов в создании неуправляемых уровней взаимодействия для .NET.

Самой большой проблемой было бы преобразование этого по существу C-интерфейса в объектно-ориентированный интерфейс, где вы вызываете методы для объектов, а не для вызова глобальных функций со структурами общедоступных членов.

Когда вы начнете писать сложные структурные графики для P / Invoke, вам самим придется столкнуться с большим количеством "магии", которая управляет тем, как управляемые примитивные типы преобразуются в неуправляемые типы. Часто использование неправильных типов приводит к ошибке во время выполнения.

С помощью управляемого C ++ (IJW - это просто работает) вы определяете управляемые структуры, классы, интерфейсы в C ++, что позволяет более естественным образом использовать базовую библиотеку и более естественный интерфейс для вашего приложения C #.

Этот является отличным обзором C ++ / CLI. Также MSDN имеет обширную документацию по всем управляемым функциям C ++.

0 голосов
/ 31 мая 2010

Да, вам необходимо объявить все эти структуры в c #. Будьте осторожны, чтобы объявить членов с правильными размерами. Например, 'long' является 32-битным в C ++, но 64-битным в C #. Для указателя или void * в C ++ используйте IntPtr в C # и т. Д.

...