2016-04-01 28 views
-2

Bazı yerel DLL'ler için bir C++/CLI sarıcı oluşturmaya çalışıyorum. Bu DLL'lerin yedisi ve daha fazlası var, bu yüzden bunları dinamik olarak yüklemem gerekiyor. Hepsinin aynı işlevleri vardır. Bu işlevleri yüklemek için yerel uygulamada LoadLibrary ve GetProcAddress harika çalıştı.Yerel işlevler için Sarıcı

Ne zaman bir DLL yükler ve Initialize çağrısı, AccessViolationException alırsınız. Platform x86 seçiliyken C# Console uygulamasıyla test ediyorum.

GÜNCELLEME: Neden oy verdiğimi bilmiyorum. Bu soruyu google aramalarımın hiçbirinde yanıtlanmadı. Sormadan önce yarım hafta aradım. Burada aynı şey hakkındaki tüm sorular farklı bir yöntem kullanıyor. MSDN, yerel etkileşimde AccessViolations'ın ciddi programlama hatalarının işareti olduğunu söylüyor. Neyi yanlış yaptığımı göremiyorum. İplerimi sıralıyorum ve aramadan önce nullptları kontrol ediyorum. Yük fonksiyonları işe yarıyor gibi görünüyor. Bilinen hatalı işlev adlarını ya da bildiğim bir DLL yolunu yanlışsa, yükleme işleminin başarısız olduğunu söyler. Doğru yollara/işlev adlarına koyarsam, her şeyin işe yarayacağını söyler, ancak aramaya çalıştığımda çöker. Ben DLL i'm test için TSInit işlevi, aslında bu DLL herhangi bir şey yapmaz, ancak aynı arabirim ile diğer DLL'ler için bazı gerçek iş yapabilir.

Güncelleme 2:

bu çözümsüz olduğunu düşünüyorum. Dediğim gibi, aynı arayüze sahip birkaç DLL var. Şimdi, bazılarının işe yaradığını öğrendim, bazıları değil. Hepsini x86 derlediklerinden ve olduklarından emin olmak için hepsini dumpbin ile kontrol ettim. Çalışmama DLL'lerinde yanlış olan emin değilim. Yerel C++ uygulamalarında, hepsi beklendiği gibi çalışır. Bu kuralları çağıran bir sorun olabilir

+0

Böyle belirsiz bir soru için tanılama sağlayamıyorsunuz. LoadLibrary() kullanarak * değil * başlayın, bunun için hiçbir anlamı yoktur. Sadece bu DLL'lerin içe aktarma kitaplıklarını bağlayın ve ilgili .h dosyalarını dahil edin. Üç daha az arıza modu. –

+0

Erişim İhlalleri sihir değil. Örneğin bir yığın iziniz var. – MSalters

cevap

0

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 }; 
}; 

}. Tüm DLL'lerin aynı çağrı kuralı kullandığından emin olun (yani, TSRINIT tanımınıza göre WINAPI), aksi takdirde kodunuzda bozuk bozulmalarla karşılaşabilirsiniz ve DLL kodu farklı temizleme davranışları bekleyebilir. Genel bir bakış için https://msdn.microsoft.com/en-us/library/984x0h58.aspx'a bakın. Doğal C++ uygulamalarının neden işe yarayacağından emin değil - sadece vahşi bir tahmin.