C # / C ++ pInvoke советы - PullRequest
       46

C # / C ++ pInvoke советы

4 голосов
/ 18 мая 2009

Как лучше всего изменить программу на C ++ для использования с pInvoke из C # .NET CF?

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

Кроме того, многие легкие классы передаются по значению.

Я хочу создать графический интерфейс C # поверх этой кодовой базы для сенсорных устройств Windows Mobile.

Стоит ли это того?

Мне удалось получить несколько примеров работы с использованием pInvoke для вызова кода C ++ из C # .NET, но написание оболочек для каждой точки доступа и для всех возвращаемых типов STL кажется очень сложным и уродливым. Есть ли другой способ или я несколько чучела?

КСТАТИ. Управляемый C ++ недоступен, поскольку он не поддерживается ни в какой форме .NET CF.

- редактирование: У меня есть один конкретный вопрос в отношении пинвока.

Предположим, у вас есть функция, возвращающая строку C ++ по значению

std::string foo () {
   return std::string ("Hi");
}

Я понимаю, что невозможно вызвать эту функцию из C # с помощью pinvoke, потому что нет способа маршалировать строку STL, но моя проблема в том, что я даже не могу написать оболочку без выделения нового массива, потому что std :: string вернулся не в кучу.

char* foo2 () {
   return foo().c_str(); //Very bad
   //the returned pointer is released when the std::string falls out of scope.
   //and will be invalid before the caller is able to do anything with it.
}

Итак, моя проблема в том, как обернуть foo в подходящий для pInvoke формат без необходимости перераспределения всей строки.

char* foo2 () {
   std::string f = foo();
   char* waste = new char[f.length()+1];
   strcpy (waste, f.c_str());
   return f;
}

Мысль о том, чтобы выполнить вышеизложенное для каждой точки, в которой мне нужно вернуть std :: string, достаточна, чтобы заставить меня отказаться от попытки использовать C #.

Ответы [ 4 ]

3 голосов
/ 19 мая 2009

Я бы лично сказал, что оно того стоит, но я согласен с другим постом, что это нелегко.

Возможные подходы могут быть:

  1. Интерфейс C вокруг C ++ и предоставляется как DLL.
  2. COM-объекты (хотя WM не поддерживает COM-серверы, поэтому вы вынуждены использовать внутрипроцессные серверы, в основном реализацию DLL COM). Это даст вам более ОО интерфейс.
  3. Фоновый процесс, демонстрирующий какой-то API. Вы можете перейти к модалу «CE Services» или создать свой собственный API.

Все возможно и имеет свои плюсы и минусы. Что бы вы ни делали, вы не можете использовать типы STL в интерфейсе. Вы сократили до простых базовых типов, которые легко распределить между процессами. Так как вы говорите о C #, тогда COM может пойти дальше, как вы можете выставить OO интерфейс.

Я бы порекомендовал сделать интерфейс между ними как можно более простым.

1 голос
/ 19 мая 2009

То, что вы хотите сделать, совсем не просто. Если вы действительно хотели это сделать, то лучше всего создать несколько чистых интерфейсов C, которые обертывают все содержимое C ++ и STL и передают структуры, которые могут легко переходить из .net в C. В зависимости от того, насколько велика ваша кодовая база, это может быть очень сложной задачей.

Извините.

0 голосов
/ 22 июля 2010

SWIG не создает для вас обертку в стиле C для C ++? Как передать все не основы сложного с ++? Поправьте меня, если я ошибаюсь, потому что нахожусь в похожей ситуации, я хочу обернуть очень большой и сложный API C ++, представленный в dll. Мне нужно избегать искажения и неосновных типов данных, написав стиль C обертка, чтобы выставить все вещи перед Pinvoking, что невозможно без автоматизированных инструментов, учитывая размер API и сложность типов и прототипов.

0 голосов
/ 18 мая 2009

Может быть, вам следует написать оболочку com, а затем использовать инструмент .net, который автоматически создаст для вас сборку c #?

...