C # DllImport проблема - PullRequest
       6

C # DllImport проблема

4 голосов
/ 13 декабря 2010

Мой вопрос немного общий, поэтому я не ищу точного ответа, но, возможно, некоторые направления, которые помогут мне разобраться ...

На своем рабочем месте я программирую в основном на C #. У нас есть сторонняя компания, с которой мы работаем, и она предоставила нам нативный C ++ dll, который нам нужно использовать. Поскольку нужный мне метод C ++ не был представлен способом, на который легко ссылаться из C #, я поместил dll в другую Native C ++ Dll.

Так что теперь у меня есть 2 нативных C ++ библиотеки, одна обертывающая другую.

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

[DllImport("HashMethodWrapper.dll")]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string CreateHash(
            string input,
            [MarshalAs(UnmanagedType.LPStr)]StringBuilder output);

В моем консольном приложении все работает нормально, и я всегда получаю ожидаемую строку в результате.

Но когда я перемещаю его в веб-службу или веб-приложение, которое я создал (поскольку это то место, где оно мне действительно нужно), я вижу, что полученная им строка является мусором и даже непоследовательна. Кажется, будто я получаю какую-то ссылку на потерянную память или что-то в этом роде, но это только мое предположение ...

Я не знаю, почему это происходит, поскольку в моем консольном приложении все работает нормально.

У кого-нибудь есть направление, которое может мне помочь ??? ...

Заранее спасибо, gillyb

Редактировать: Я подумал, что это может быть связано с некоторыми неподкрепленными объектами, поэтому я попытался вызвать метод в фиксированном выражении, что-то вроде:

unsafe public static string CreateHashWrap(string pass)
{
    String bb;
    StringBuilder outPass = new StringBuilder();
    fixed (char* resultStr = CreateHash(pass, outPass))
    {
        bb = new String(resultStr);
    }
    return bb;
}

... но это все равно не помогло мне. Это правильный способ закрепления объектов?

2-е редактирование: Подпись метода в C ++ выглядит так:

extern "C" __declspec(dllexport) char *CreateRsaHash(char *inputPass, char *hashPass);

3-е редактирование: Я изменил подпись метода на

extern "C" __declspec(dllexport) bool CreateRsaHash(char *inputPass, char *hashPass);

и искомое возвращаемое значение помещается в параметр *hashPass.

Теперь я создал простое консольное приложение для его тестирования. Когда я вставляю DllImport в мой основной класс и напрямую вызываю метод, все прекрасно работает, но когда я перемещаю DllImport, оборачиваю метод в другой класс и вызываю этот класс из метода Main 'Console, я получаю исключение StackOverflow!

У кого-нибудь есть идеи, почему это происходит ??

Ответы [ 4 ]

2 голосов
/ 13 декабря 2010

Попробуйте , указав емкость StringBuilder , прежде чем передать ее в метод взаимодействия.

1 голос
/ 13 декабря 2010

Это очень трудно узнать из редкой информации, но если бы мне пришлось угадывать, я бы сказал, что вам нужно убедиться, что вы закрепляете выходной объект. Также я, вероятно, изменил бы выходной параметр на какой-то другой тип, кажется довольно странным, что StringBuilder работает вообще откровенно.

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

Вот действительно грубая версия того, что я имею в виду, прикрепляя:

string input = "...";
StringBuilder output = new StringBuilder();
var handle = System.Runtime.InteropServices.GCHandle.Alloc(output, GCHandleType.Pinned);
try
{
    CreateHash(input, output);
}
finally
{
    handle.Free();
}
0 голосов
/ 13 декабря 2010

Я нашел решение своей проблемы, и теперь я чувствую себя немного (если не совсем!) Глупо ...: - |

Я использовал метод LoadLibrary() в C ++ для динамического вызова метода издругой родной dll.Проблема заключалась в том, что я не дал методу никакого пути, а только имя файла DLL.В .net он выполнял бы поиск в текущей папке, но, похоже, в нативном коде это не работает таким образом.

Большая проблема в моих методах программирования, очевидно, заключается в том, что я этого не делалполностью покрыть обработку ошибок в моем родном C ++ dll!

Все ответы, которые я получил на этой странице, были не зря, хотя ...

Как только я узнал, что у меня были проблемы с каталогомпути, я столкнулся с различными исключениями при попытке получить доступ к поврежденной памяти и т. д. А затем мне нужно было создать закрепленные объекты и объявить размер для моего объекта StringBuilder.

Спасибо всем за помощь !!

:)

0 голосов
/ 13 декабря 2010

Я хотел бы рассмотреть деформацию внутри совместно используемой сборки / dll C # вместо d ++ c ++, а затем попытаться заставить ваше консольное приложение работать с dll.В любом случае, рекомендуется оборачивать внешние зависимости таким способом.
В противном случае некоторые традиционные проблемы - 32 или 64 бита, путь загрузки в общую библиотеку.Это действительно только строка или что-то более сложное?

...