2016-04-01 3 views
-2

Я пытаюсь создать обертку C++/CLI для некоторых родных DLL. Есть семь из этих DLL и больше в будущем, поэтому мне нужно загрузить их динамически. Все они имеют один и тот же набор функций. LoadLibrary и GetProcAddress отлично работали в приложении для загрузки этих функций.Wrapper для собственных функций

Всякий раз, когда я загружаю DLL и вызываю Initialize, я получаю AccessViolationException. Im тестирование с помощью приложения C# Console с выбранной платформой x86.

ОБНОВЛЕНИЕ: Не знаете, почему я проголосовал. На этот вопрос не ответил ни один из моих поисковых запросов. Я искал полчаса, прежде чем даже спросил. Все вопросы здесь примерно то же самое, используя другой метод. MSDN говорит, что AccessViolations в собственном взаимодействии являются признаком серьезных ошибок программирования. Я не вижу, что я делаю неправильно. Я сортирую свои строки и проверяю nullptrs перед вызовом. Функции загрузки, похоже, работают. Если я использую известные имена неправильных функций или неверный путь к DLL, он говорит мне, что загрузка не удалась. Если я ввожу правильные имена путей/функций, в нем говорится, что все сработало, но затем сбой, когда я пытаюсь его вызвать. Функция TSInit для DLL, которую я тестирую, фактически ничего не делает в этой конкретной DLL, однако она может сделать некоторую фактическую работу для других DLL с тем же интерфейсом.

Update 2:

Я думаю, этот вопрос без ответа. Как я уже сказал, есть несколько DLL с одним и тем же интерфейсом. Теперь я обнаружил, что некоторые из них работают, а некоторые нет. Я проверил все их с помощью dumpbin, чтобы подтвердить, что все они составлены x86, и они есть. Я не уверен, что не так с DLL, которые не работают. В родных приложениях C++ все они работают так, как ожидалось.

typedef long (WINAPI *TSRINIT)(long lType, HWND hParent, RECT *pRect); 

namespace Imagery 
{ 
    public ref class Recongizer 
{ 
public: 
    Recongizer(String^ DllPath) { LoadRecongizer(DllPath); } 
    ~Recongizer() { UnloadLibrary(); } 
    bool LoadRecongizer(String^ DllPath) 
    { 
     HInstance = ::LoadLibrary(msclr::interop::marshal_as<std::wstring>(DllPath).c_str()); 
     if (HInstance == nullptr) return false; 
     if (!LoadFunctions()) return false; 
     return true; 
    } 
    long Initalize(long lType) 
    { 
     if (HInstance == nullptr || TSInit == nullptr) return 0; 
     return TSInit(0, nullptr, nullptr); 
    } 
private: 
    void UnloadLibrary() 
    { 
     if (HInstance != nullptr) ::FreeLibrary(HInstance); 
    } 
    bool LoadFunctions() 
    { 
     TSInit = (TSRINIT)::GetProcAddress(HInstance, "TSRInit"); 
     if (TSInit == nullptr) 
     { 
      ErrorMessage = "TSRInit could not be loaded."; 
      return false; 
     } 
     return true; 
    } 
    property String^ ErrorMessage; 
private: 
    HINSTANCE HInstance{ nullptr }; 
    TSRINIT TSInit{ nullptr }; 
}; 

}

+0

Вы не можете получить диагностику для такого неопределенного вопроса. Начните с * not * с помощью LoadLibrary(), нет никакого смысла в этом. Просто свяжите библиотеки импорта этих DLL и #include соответствующие файлы .h. Три режима отказа. –

+0

Нарушения доступа не являются волшебными. Например, у вас есть трассировка стека. – MSalters

ответ

0

Это может быть проблема с вызовом конвенции. Убедитесь, что все библиотеки DLL используют одно и то же соглашение о вызове (т. Е. WINAPI в соответствии с вашим определением TSRINIT), в противном случае вы можете столкнуться с повреждением стека, поскольку ваш код и код DLL могут ожидать различного поведения очистки. См. https://msdn.microsoft.com/en-us/library/984x0h58.aspx. Не уверен, почему родные приложения на C++ будут работать, - просто дикая догадка.

Смежные вопросы