доступ к неуправляемой dll в С++ из двух разных приложений (служба Windows С# и программная платформа)

Я провел несколько часов в поисках ответа, поэтому понял, что если я задам себе этот вопрос, то смогу, наконец, найти решение своей проблемы. Во-первых, чтобы описать, что я хочу сделать: НЕУПРАВЛЯЕМЫЙ КОД ДОЛЖЕН БЫТЬ РАЗДЕЛЕН ОБОРОТКОЙ DLL И ПРОГРАММНОЙ ПЛАТФОРМОЙИтак, , чтобы описать дизайн выше, у меня есть плагин .dll, написанный на чистом С++ (я не хочу, чтобы он содержал какой-либо код .Net). Этот плагин С++ будет использоваться с программной платформы. Теперь я хочу, чтобы служба Windows С# взаимодействовала с программной платформой, но она может делать это только через dll С++. По этой причине я обернул всю функциональность плагина C++ в Wrapped Dll (я экспортировал функциональность), и я использую Wrapped Dll в службе Windows C#.

Теперь у меня есть тестовый метод, чтобы проверить, нормально ли работает экспорт функций С++ (всего лишь простой метод, возвращающий сумму двух целых чисел), и я вижу, что служба Windows может взаимодействовать с неуправляемой dll С++ в правильный путь, я получаю правильные результаты. У меня проблема, когда я пытаюсь взаимодействовать с программной платформой через неуправляемую dll С++. Я получаю следующую ошибку:

Ошибка из-за повреждения памяти

Я понял, что ошибка должна быть связана с тем, что неуправляемая dll не может быть доступна программной платформе и обернутой dll одновременно. Чтобы решить эту проблему, я обнаружил, что решение состоит в том, чтобы добавить неуправляемую dll в GAC. Но чтобы поместить dll в GAC, у dll должно быть строгое имя, но я обнаружил, что не могу подписывать строгое имя для неуправляемого кода, если у меня не включен параметр /clr. Но когда у меня включена эта опция, неуправляемая dll не компилируется.

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

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

Спасибо


person CompuPlanet    schedule 25.11.2014    source источник
comment
Похоже, в вашей обертке что-то идет не так. Я предполагаю, что некоторые проблемы с указателем. Не могли бы вы показать нам больше кода?   -  person t3chb0t    schedule 25.11.2014
comment
@ t3chb0t [DllImport("C:\\Path\\MyNativeDll.dll", EntryPoint = CheckUserGroup")] public static extern bool _CheckUserGroup(string group); Вот как я импортирую метод из NativeDll в ManagedDll. public bool CheckUserGroup(string group) { return _CheckUserGroup(group); } И вот как это взаимодействует. --› Этот метод взаимодействует с программной платформой, получает результат и возвращает его в manageDLL, а из управляемой Dll — в службу Windows c#. Но,   -  person CompuPlanet    schedule 25.11.2014
comment
Если я использую [DllImport("C:\\Path\\MyNativeDll.dll", EntryPoint = "TestMethod")] public static extern int _TestMethod(int x, int y); , который выполняет расчет для неуправляемого плагина без взаимодействия с программной платформой, результаты, которые я получаю в службе Windows С#, верны. Итак, именно поэтому я говорю, что я не уверен, что это ошибка в обертке.   -  person CompuPlanet    schedule 25.11.2014
comment
Пожалуйста, добавьте все свои dll в папку приложения и не используйте C:\\Path\\MyNativeDll.dll. Кроме того, переместите все библиотеки DLL платформы в каталог.   -  person BendEg    schedule 25.11.2014
comment
Я считаю, что гораздо проще использовать C++/CLI для упаковки собственного кода/dll. Он может взаимодействовать с родным C++ намного лучше, чем с C#.   -  person t3chb0t    schedule 25.11.2014
comment
Я только что попробовал то, о чем вы просите, все находится в том же каталоге. Тем не менее я получаю ту же ошибку. Я не думаю, что это связано с каталогами или с тем, как я упаковываю неуправляемую Dll :(   -  person CompuPlanet    schedule 25.11.2014
comment
@ t3chb0t да, я знаю, что это было бы намного проще сделать. Проблема в том, что если я использую c++/CLI для переноса своего кода, я использую .NET, и я не хочу использовать .Net в правой части моего дизайна (см. выше справа).   -  person CompuPlanet    schedule 25.11.2014
comment
Оболочка C++/CLI будет располагаться слева. Он заменит оболочку C # и скомпилирует в .NET, но сможет общаться с родной dll.   -  person t3chb0t    schedule 25.11.2014
comment
хорошо, теперь я понимаю, что вы говорите. Вы говорите, что я должен использовать другой способ обернуть собственную dll вместо того, который я использую. Но все же, прежде чем начать это делать, я не думаю, что это проблема обертки. Потому что, если бы это было так, как я могу использовать метод Test и получить правильные результаты?   -  person CompuPlanet    schedule 25.11.2014
comment
Можете ли вы предоставить нам код?   -  person BendEg    schedule 25.11.2014
comment
extern "C" MYNATIVEDLL_API bool __cdecl CheckUserGroup(LPCSTR clientGroup) так определяется метод. И внутри метода я вызываю API программной платформы, чтобы получить UserGroup, и я сравниваю его с тем, который я получаю в качестве параметра. Функциональность правильная, так как я использовал ее раньше. Работающий TestMethod таков: extern "C" SPOTOPTIONMTPLUGIN_API int __cdecl TestMethod(int x, int y) { return x+y; } В моих первых двух комментариях выше я показываю вам код в WrappedDll. Это код из библиотеки Native c++.   -  person CompuPlanet    schedule 25.11.2014
comment
У вас есть это: stackoverflow.com/questions/2417494/ ?   -  person BendEg    schedule 25.11.2014
comment
Как мне его использовать?   -  person CompuPlanet    schedule 25.11.2014


Ответы (1)


Ваша неуправляемая dll и все ее зависимости должны находиться в той же папке, что и ваше приложение (.exe). Вам не нужен GAC. Если вы хотите хранить свои DLL в другом месте, просто используйте:

р (вызов:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool AddDllDirectory(string lpPathName);

И при запуске вашего приложения:

if (System.Environment.OSVersion.Version.Major > 5)
{
    AddDllDirectory(System.Windows.Forms.Application.StartupPath + "\\bin64");
}
else
{
    SetDllDirectory(System.Windows.Forms.Application.StartupPath + "\\bin64");
}

Также убедитесь, что вы не перепутали архитектуру x86 и x64. Кроме того, убедитесь, что вы используете правильный CallingConvention. Хороший пример: необработанное исключение: System.AccessViolationException: Attempted читать или писать

person BendEg    schedule 25.11.2014
comment
Спасибо за ваш ответ. У меня нет проблем с использованием неуправляемой dll либо из программной платформы, либо из службы Windows С#, если то, что я пытаюсь сделать, не мешает работе С# и программной платформы. Я имею в виду, что я могу получить доступ к тестовому методу из оконной службы С# (см. описание проблемы), и он работает нормально, но если я попытаюсь получить доступ к методу из неуправляемого кода, который должен взаимодействовать с программной платформой для выполнения что-то и вернуть ответ службе С#, я получаю сообщение об ошибке. - person CompuPlanet; 25.11.2014
comment
Так что моя проблема не в том, что я не могу получить доступ к dll, а в том, что я хочу взаимодействовать с двух сторон, используя неуправляемый код. Есть идеи? - person CompuPlanet; 25.11.2014
comment
У вас есть все dll с вашей программной платформы в нужном месте (в папке вашего приложения)? Не могли бы вы объяснить, что представляет собой ваша программная платформа? - person BendEg; 25.11.2014
comment
да. Программная платформа - это платформа, используемая для финансовых целей, она содержит информацию о клиентах (имена пользователей, пароли, балансы, заказы и т. д.). Вы можете управлять тем, как вы хотите выполнять действия (депозиты, снятие средств и т. д.) - person CompuPlanet; 25.11.2014