Как сделать встроенный API, чтобы быть товарищеской встречей PInvoke?
существуют некоторые подсказки относительно того, как изменить собственные программы, которые будут использоваться с P/Invoke здесь. Но прежде чем я даже пишу собственные программы, каковы вещи, я должен посмотреть для создания моих программ/библиотеки PInvoke дружественный?
использование C или C++ прекрасно.
обновление:
если я пишу API C, что является вещами, я должен сделать так, чтобы Это был P/Invoke-able, использующий синтаксис C# как следующее:
[DLLimport("MyDLL.dll")]
действительно ли возможно сделать то же с собственным кодом/библиотекой C++?
Сводка/Перефразировать Некоторых Подсказок для создания дружественного встроенного API P/Invoke:
+ параметры должны иметь собственные типы (интервал, символ*, плавание...)
+ меньше параметров лучше
+ если динамическая память выделяется и передается управляемому коду, удостоверьтесь, что создали "более чистую" функцию, которая является также p/invoked
+ обеспечьте образцы и/или модульные тесты, которые иллюстрируют, как назвать API от.NET
+ обеспечьте C++ / обертка
по определению, каждая нативная функция может быть P /, вызываемая из управляемого кода. Но для того, чтобы быть настроенным P / вызывать, функция должна иметь как можно меньше параметров, что должно быть нативных типов (int, char *, float, ...). Кроме того, если функция выделяет память на некотором указателе, который возвращается к управляемому коду, убедитесь, что вы записали свою счетную часть, которая освободит указатель как управляемый код, не удается бесплатно, выделяемую память, выделенную из неуправляемого кода.
На самом деле, это возможно.
Для реализации функциональных возможностей необходимо определить TypeListener
. Что-то вроде следующего в определении модуля:
bindListener(Matchers.subclassesOf(MyInitClass.class), new TypeListener() {
@Override
public <I> void hear(final TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
typeEncounter.register(new InjectionListener<I>() {
@Override
public void afterInjection(Object i) {
MyInitClass m = (MyInitClass) i;
m.init();
}
});
}
});
-121--970020- Можно преобразовать подстановочный запрос в регулярное выражение и использовать его для сопоставления; RE всегда может быть преобразован в DFA (дискретный конечный автомат), и они являются эффективными (время линейного эфира) и малой константой.
-121--3003487-Вместо использования P/Invoke, если вы сами управляете собственной библиотекой, вы можете написать набор классов C + +/CLI, которые переносят собственные вызовы. Во многих случаях это будет работать лучше, чем использование platform invoke, и вы получите дополнительное преимущество правильности типа. Например, если у вас есть какой-то C API как следующий (он не делает ничего полезного, я просто добавил указатели и структуры, чтобы усилить тот факт, что это собственный код):
struct SomeStruct {
int a, b;
int* somePtr;
};
int foo(struct SomeStruct* a, int b) {
*a->somePtr = a->a + a->b;
return a->b * *a->somePtr + b;
}
Можно создать класс C + +/CLI, чтобы обернуть его:
public ref class MyNativeAPI {
private:
SomeStruct* x;
public:
MyNativeAPI() {
x = new SomeStruct;
}
~MyNativeAPI() {
delete x;
}
int Foo(int a) {
pin_ptr<SomeStruct*> ptr = this->x;
return foo(ptr, a);
}
}
Затем можно вызвать это в C #:
MyNativeAPI a = new MyNativeAPI();
if(a.Foo(5) > 5) { ... };
Вам придется прочитать больше на C + +/CLI, чтобы понять новые элементы управления, которые у вас есть как в управляемой куче, так и в собственной куче, и предостережения к смешиванию двух (как pin _ ptr
, которые я использовал выше), но в целом это гораздо более элегантное решение для достижения собственного взаимодействия в .NET.
Укажите пример правильно, вызывая его из C # или .NET, еще лучше предоставить классу .NET, который включает все ваши методы
, написание простого теста на единицу с NUNIT это доказывает, что ваш код работает правильно когда вызывается из .NET способ сделать это.
Также помните, что разработчики .NET, которые, вероятно, вызывают ваш код, вряд ли знают много о C ++ или не знают размеров разных типов данных и т. Д. Или как эти типы отображаются на атрибуты PINVOKE.
Прежде всего подумайте о том, как вы хотите, чтобы ваш клиентский код выглядеть, а затем разработать API, который позволяет ему.