использование C ++ DLL в приложении C # windows: получение ошибки & quot; точка входа не найдена & quot;

Я новичок в использовании библиотек C ++ в C #, а также в программировании на C ++ в целом. У меня есть библиотека DLL, созданная из кода C ++, который, по моему мнению, является «управляемым» кодом, поскольку имя библиотеки DLL «TestManaged.dll». Я не уверен на 100%, является ли код dll / C ++ управляемым / неуправляемым.

Я хочу использовать классы и методы этой DLL в моем C# windows forms application код. В этой DLL есть несколько классов. Когда я проверял эти классы и методы внутри этих классов в Object Browserвсе они имеют Public идентификатор.

До сих пор я добавил эту DLL к своим ссылкам на код приложения C #. В моем вопросе я расскажу о трех классах: Product, ReqStatus, ProductData, Я мог бы создать объект (ы) для различных классов этой DLL следующим образом.

Product testCall = new ProductClass();

Есть еще один класс под названием ProductData в этой DLL, и я мог бы получить код C ++ для этого класса, который заключается в следующем. В этом случае, ProductData отображается как класс в Object Browser в C #, где это на самом деле структура в коде C ++. Я не уверен, если это важно, чтобы ответить на мой вопрос (в конце).

Ниже приведен код C ++, который определяет ProductData структура — ProductData.h файл.

#ifdef WIN32_MANAGED
public ref  struct ProductData
#else
struct ProductData
#endif
{
UINT32 ProductId;           //!< Product ID
UINT32 PRoductRev;         //!< Build Revision
};

Ниже приведен код C ++, который определяет ReqStatus enum — ReqStatus.h файл. Я создал такое же перечисление в моем коде C # без указания идентификатора.

enum ReqStatus
{
SUCCESS,            //!< Method was successful

//Connection errors
NOT_CONNECTED,      //!< Connection not open
CONN_TIMEOUT,       //!< Connection timed out commuincating with device
};

Теперь есть два метода, которые я хочу вызвать, и у меня проблемы с обоими:

Способ 1: это getProductData метод внутри Product класс, который принимает объект ProductData введите в качестве параметра и возвращает ReqStatus который является типом перечисления в C ++. Итак, следующее заявление gerProductData метод (как видно из Object Browser):

public ReqStatus getProductData(ProductData data)

Делькарация C ++ того же метода: (Фактический метод слишком длинный и, следовательно, просто дает объявление): Этот метод находится внутри Prodcut.cpp файл

ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)

PLATFORM_PTR определяется как показано ниже Platform.h

#ifdef WIN32_MANAGED
#define PLATFORM_PTR ^
#else
#define PLATFORM_PTR *
#endif

Способ 2: это getConnected метод внутри Product класс, который принимает массив символов (я не уверен в этом) и объект ProductData введите в качестве параметра и возвращает ReqStatus который является типом перечисления в C ++. Итак, следующее заявление getConnected метод (как видно из Object Browser):

public ReqStatus getConnected(sbyte* someChar, ProductData data)

Делькарация C ++ того же метода: (Фактический метод слишком длинный и, следовательно, просто дает объявление): Этот метод находится внутри Prodcut.cpp файл

ReqStatus Product::getConnected(const char *someChar, ProductData PLATFORM_PTR data)

Код C ++ вызывает методы следующим образом:

private : Product^  _testProduct;
testProduct = gcnew Product();
ProductData ^ data = gcnew ProductData();

int portNum = Decimal::ToInt16(7);
char portName[32];
_snprintf(&portName[0], sizeof(portName),"COM%d", portNum);
ReqStatus status = _testProduct->getConnected(&portName[0], data); //Calling getConnected

Внутренний звонок getProductData метод внутри getConnected метод.

ReqStatus status = getProductData(data); //data is the same which was passed to the getConnected method

Мой код C # выглядит следующим образом, и я получил ошибки при обоих вызовах методов: я поместил ошибки в одну строку в приведенном ниже фрагменте кода. Оба метода независимы. Это просто, что getProductData вызывается из getConnected метод в коде C ++. Я хотел проверить, могу ли я позвонить как по отдельности.

ProductData pData = new ProductData(); // OK
Product _testProduct = new Product();  // OK

ReqStatus status1 = _testProduct.getConnected("COM5", pData ); //Error 1: The best overloaded method getConnected has some invalid arguments
ReqStatus status2 = (ReqStatus)_testProduct.getProductData(pData ); // Error 2: Method is inaccessible due to its protection level

В отношении ошибки 1 я пытался найти решения из различных статей на StackOverflow и других форумах, но не смог ее решить. Просто для справки, я попытался изменить «SomePortCOM» следующим образом, но он не работает.

ОБНОВИТЬ: Этот код теперь работает нормально, и я не вижу ошибку 1 (неверные аргументы). Теперь мне нужно только избавиться от ошибки 2 (ошибка уровня защиты). Пожалуйста, предоставьте любые предложения. Спасибо.

String str = "COM5";
byte[] bytes = Encoding.ASCII.GetBytes(str);
unsafe
{
fixed (byte* p = bytes)
{
sbyte* sp = (sbyte*)p;
//SP is now what you want
ReqStatus status1 = _testProduct.getConnected(sp, pData );
}
}

Что касается Error2, я искал так много блогов и обнаружил, что одним из возможных решений может быть использование DLLImport, я тоже попробовал это, и у меня возникла следующая проблема:

C # объявление DLLImport:

[DllImport("TestManaged.dll",EntryPoint="getConnected")]
public static extern ReqStatus getConnected(String SerialPort, ref ProductData pData);

Я вызываю эту функцию, как показано ниже из моего кода C #:

ProductData pData = new ProductData();
String str = "COM7";
ReqStatus status1 = getConnected(str, ref pData);

Тем не менее, я получаю Entry point not found ошибка. Я попытался запустить функцию dumpbin, чтобы получить список функций, экспортируемых этой DLL. Но я не вижу никаких функций. Скорее просто случайный вывод, как показано ниже.

Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.Dump of file C:\Rumit\TestManaged.dll

File Type: DLL

Summary

2000 .data
22000 .rdata
1000 .reloc
1000 .rsrc
13000 .text

ОБНОВИТЬ:
Кроме того, я не вижу каких-либо методов в этой DLL через Dependency Walker.
Теперь у меня есть исходный код для C ++. Но я довольно плохо знаком с C ++. В случае, если требуется внести какие-либо изменения в код C ++, просим дать указания.

С Уважением,
Rumit

1

Решение

 enum ReqStatus

Это ваше самое большое зависание. Он объявляет собственный тип перечисления, он не может использоваться в управляемом коде и делает любой код, который его использует, недоступным. Вы должны объявить управляемую версию с enum class Ключевое слово, как это:

public enum class ReqStatus {
// etc...
}
1

Другие решения

Небезопасный блок вокруг вашего кода сделает так, что ваша сборка не может быть проверена на наличие протоколов безопасности, так что будьте осторожны с этим. Когда я вызывал методы из C ++ (нативные или нет) из C #, мне приходилось использовать PInvoke (Platform Invoke) для их вызова. Что касается уровня защиты, я знаю, что вы сказали, что в C ++ все открыто, но если вы новичок в C ++, возможно, вы допустили быструю синтаксическую ошибку. В C # всем методам должен предшествовать спецификатор хранилища (открытый, защищенный и т. Д.), Но в C ++ вы помещаете спецификатор хранилища с двоеточием, и все, что находится между хранилищем TH и следующим объявленным хранилищем, будет из этого хранилища. тип. Может быть, это ваша проблема?

0

Спасибо, Ганс, за указание на проблему. Просто я определил перечисление как «public». Но я не уверен, что вы указали «класс» по ошибке или он был преднамеренным, так как он давал мне столько ошибок, что он не воспринимался как перечисление и запрашивал объект в каждом месте, где я использовал перечисление , Дайте мне знать, если я что-то здесь неправильно понял.

Итак, я заработал, просто опубликовав enum. Тем не менее, я до сих пор не могу найти, как передать правильные значения в эту функцию C ++ из C #. (Ошибка1 в моем оригинальном посте).

Когда я отлаживаю код C ++, он передает значение «0x0034E808« COM5 »(я предполагаю, что это место в памяти и значение?) Для первого параметра getConnected метод. Я попытался передать это значение, реализовав небезопасный метод (объясненный в моем исходном сообщении об ошибке 1), он передает «0x0277aab8» (опять же, кажется, некоторый адрес памяти), но не смог подключиться к нему (получение ошибок тайм-аута последовательного порта). Я неправильно передаю значение по сравнению с методом C ++?

С Уважением,
Rumit

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector