достъп до неуправляван dll в c++ от две различни приложения (услуга на c# windows и софтуерна платформа)

Прекарах няколко часа в търсене на отговора, така че разбрах, че ако се запитам, най-накрая мога да намеря решение на проблема си. Първо, за да опиша какво искам да направя: НЕУПРАВЛЯВАНИЯТ КОД ТРЯБВА ДА БЪДЕ СПОДЕЛЕН ОТ ОПАКОВАНА DLL И СОФТУЕРНА ПЛАТФОРМАТака че , за да опиша дизайна по-горе, имам .dll плъгин, написан на чист c++ (не искам да съдържа никакъв .Net код). Този c++ плъгин ще се използва от софтуерна платформа. Сега искам услугата c# windows да взаимодейства със софтуерната платформа, но може да го направи само чрез c++ dll. Поради тази причина увих цялата функционалност на плъгина c++ в Wrapped Dll (експортирах функционалността) и използвам Wrapped Dll в услугата на c# windows.

Сега имам тестов метод, за да проверя дали експортирането на функционалността на c++ работи добре (само прост метод, който връща сумата от две цели числа) и виждам, че услугата на windows може да взаимодейства с неуправляваната dll на c++ в правилен начин, получавам правилните резултати. Проблемът, който имам, е, когато се опитвам да взаимодействам със софтуерната платформа чрез c++ unmanaged dll. Получавам следната грешка:

Грешка за повредена памет

Разбрах, че грешката трябва да е, защото неуправляваната dll не може да бъде достъпна от софтуерната платформа и Wrapped 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); } И ето как си взаимодейства. --› Този метод взаимодейства със софтуерната платформа, получава резултата и го връща към управляваната DLL и от управляваната Dll към услугата c# windows. Но,   -  person CompuPlanet    schedule 25.11.2014
comment
Ако използвам [DllImport("C:\\Path\\MyNativeDll.dll", EntryPoint = "TestMethod")] public static extern int _TestMethod(int x, int y); , който прави изчислението на неуправляемия плъгин, без да взаимодейства със софтуерната платформа, резултатите, които получавам в услугата c# 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 вместо този, който използвам. Но все пак, преди да започна да правя това, не мисля, че проблемът е в обвивката. Защото, ако беше, как мога да използвам метода на теста и да получа правилни резултати?   -  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++ dll.   -  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 файлове някъде другаде, просто използвайте:

p(Извикване:

[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: опит за четене или писане

person BendEg    schedule 25.11.2014
comment
Благодаря Ви за отговора. Нямам никакъв проблем да използвам неуправляваната dll, нито от софтуерната платформа, нито от услугата c# windows, стига това, което се опитвам да направя, да не пречи на c# и софтуерната платформа. Имам предвид, че мога да осъществя достъп до тестовия метод от услугата на прозореца на c# (вижте описанието на проблема) и той работи добре, но ако се опитам да осъществя достъп до метод от неуправлявания код, който трябва да взаимодейства със софтуерната платформа, за да направи somathing и да върна отговора на услугата c#, получавам грешката. - 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