Взаимодействие с C ++: Как я могу назвать класс C # из нативного C ++, при этом класс не является статичным? - PullRequest
7 голосов
/ 07 октября 2010

У меня есть большое приложение, написанное на родном C ++.У меня также есть класс в C #, который мне нужно вызвать.

Если бы класс C # был статическим, то это было бы тривиально (есть много примеров в Интернете) - просто напишите смешанную оболочку C ++ / CLI,экспортируйте интерфейсы, и все готово.

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

Кто-нибудь сталкивался с этой проблемой раньше - как экспортировать нестатический класс C # в собственный C ++?


Обновление 2010-11-09

Окончательное решение: пробовал COM, это работало хорошо, но не поддерживало структуры.Итак, пошел с оболочкой C ++ / CLI, потому что мне абсолютно необходимо было иметь возможность передавать структуры между C ++ и C #.Я написал оболочку .dll в смешанном режиме на основе кода:

Поскольку целевой класс был нестатичным, мне пришлось использовать шаблон синглтона, чтобы убедиться, что я был толькосоздание одной копии целевого класса.Это гарантировало, что все было достаточно быстро, чтобы соответствовать спецификациям.

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

Ответы [ 3 ]

10 голосов
/ 07 октября 2010

C ++ / CLI или COM-взаимодействие работают так же хорошо с нестатическими классами, как со статическими. Используя C ++ / CLI, вы просто ссылаетесь на свою сборку, которая содержит нестатический класс, а затем вы можете использовать gcnew для получения ссылки на новый экземпляр.

Что заставляет вас думать, что это невозможно с вашим нестатическим классом?

РЕДАКТИРОВАТЬ: здесь есть пример кода здесь .

using namespace System;

public ref class CSquare
{
private:
    double sd;

public:
    CSquare() : sd(0.00) {}
    CSquare(double side) : sd(side) { }
    ~CSquare() { }

    property double Side
    {
    double get() { return sd; }
    void set(double s)
    {
        if( s <= 0 )
        sd = 0.00;
        else
        sd = s;
    }
    }

    property double Perimeter { double get() { return sd * 4; } }
    property double Area { double get() { return sd * sd; } }
};

array<CSquare ^> ^ CreateSquares()
{
    array<CSquare ^> ^ sqrs = gcnew array<CSquare ^>(5);

    sqrs[0] = gcnew CSquare;
    sqrs[0]->Side = 5.62;
    sqrs[1] = gcnew CSquare;
    sqrs[1]->Side = 770.448;
    sqrs[2] = gcnew CSquare;
    sqrs[2]->Side = 2442.08;
    sqrs[3] = gcnew CSquare;
    sqrs[3]->Side = 82.304;
    sqrs[4] = gcnew CSquare;
    sqrs[4]->Side = 640.1115;

    return sqrs;
}
3 голосов
/ 07 октября 2010

На ум приходят два варианта.

  1. Представьте класс как объект COM и используйте его как объект COM из C ++.
  2. Создать статический класс C #, который предоставляет интерфейс для взаимодействия с нестатическим классом C #.
1 голос
/ 08 октября 2010

Я исследовал эту тему пару лет назад: я хочу использовать библиотеки log4net и Npgsql из собственного кода, который компилируется даже без ключа / clr.

Основная идея этой техники описана Полом ДиЛаскья в его двух замечательных статьях:

Управляемый код в Visual Studio 2005

Используйте нашу библиотеку ManWrap, чтобы получить лучшее из .NET в родном коде C ++

Основная идея в этом решении, что интеллектуальные указатели gcroot и intptr_t имеют абсолютно одинаковое представление в памяти. И мы создаем макрос с именем GCROOT (T), который использует gcroot в управляемом коде и intptr_t в неуправляемом. И что мы создаем DLL с собственным интерфейсом и управляемой реализацией и используем эту DLL из нашего собственного кода.

Мне было довольно легко создать какой-нибудь адаптер для моих управляемых классов и использовать их в родном мире C ++ и скомпилировать мой исходный код даже без ключа / clr.

...