无法在C#Project中重新加载C++ dll

And*_*ndy 3 .net c# c++ dll

我希望那里有人可以帮助我将C++ DLL加载和重新加载到C#项目中.

我正在使用文件选择器将C++ DLL加载到我的项目中,然后将其复制到名为Process.dll的文件中.然后我使用这个dll来做它的事情然后我需要能够加载一个新的dll并让它做它的事情.

所以它是这样的:

  1. 用户选择一个DLL
  2. dll被复制到Processor.dll
  3. 使用dll import的我的Processor类来使用dll
  4. 使用DLL并调用其各种功能等
  5. 回到1.

我有2节课

  1. ProcessTab - 具有GUI并在ProcessPlugin中调用类的C#类
  2. ProcessPlugin - 调用C++类的C#类,它使用dllImport等

代码如下所示:

class ProcessorTab
{
    private void buttonLoadProcDll_Click(object sender, RoutedEventArgs e)
    {
        // Open dll and copy it to "\\Processor.dll"

        processorPlugIn = new ProcessorPlugIn(this);
        return;
    }

    private void DestroyProcessor_Click(object sender, RoutedEventArgs e)
    {
        processorPlugIn.UnloadModule("Processor.dll");
        processorPlugIn = null;
    }
}

class ProcessorPlugIn
{ 
    public const string PluginName = "Processor.dll";

    public LibraryInfo info;
    ErrorCode err;
    private IntPtr pRxClass;
    private IntPtr pTxClass;

    [DllImport("kernel32", SetLastError = true)]
    static extern bool FreeLibrary(IntPtr hModule);

    [System.Runtime.InteropServices.DllImportAttribute(PluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern ErrorCode VE_ProcessorPluginLib_Rx_API_Constructor(ref IntPtr pRx);

    [System.Runtime.InteropServices.DllImportAttribute(PluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern ErrorCode VE_ProcessorPluginLib_Rx_API_Destructor(ref IntPtr pRx);

    [System.Runtime.InteropServices.DllImportAttribute(PluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern ErrorCode VE_ProcessorPluginLib_Tx_API_Constructor(ref IntPtr pTx);

    [System.Runtime.InteropServices.DllImportAttribute(PluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern ErrorCode VE_ProcessorPluginLib_Tx_API_Destructor(ref IntPtr pTx);

    public ProcessorPlugIn(MainWindow mWindow)
    {
        pRxClass = new IntPtr();
        pTxClass = new IntPtr();

        if (VE_ProcessorPluginLib_Rx_API_Constructor(ref pRxClass) != ErrorCode.EC_OK) // ERROR HERE: AccessViolationException was unhandled
            MessageBox.Show("Error constructing Rx");

        if (VE_ProcessorPluginLib_Tx_API_Constructor(ref pTxClass) != ErrorCode.EC_OK)
            MessageBox.Show("Error constructing Tx");
    }

    public void UnloadModule(string moduleName)
    {
        if (VE_ProcessorPluginLib_Rx_API_Destructor(ref pRxClass) != ErrorCode.EC_OK)
            MessageBox.Show("Error destropying Rx");

        if (VE_ProcessorPluginLib_Tx_API_Destructor(ref pTxClass) != ErrorCode.EC_OK)
            MessageBox.Show("Error destropying Rx");

        foreach (ProcessModule mod in Process.GetCurrentProcess().Modules)
        {
            if (mod.ModuleName == moduleName)
            {
                FreeLibrary(mod.BaseAddress);
            }
        }
    }     
}
Run Code Online (Sandbox Code Playgroud)

一切正常,我调用C++ DLL中的方法并获得预期的输出等,但当我尝试销毁它并重新加载它时,我得到一个错误AccessViolationException未处理,如代码中的注释所示.

有谁知道如何解决这个问题?

提前谢谢了

Luc*_*ski 5

P/Invoke并不意味着处理这种情况.它假设库永远不会改变,我相信它不会指望你调用FreeLibrary它导入的模块.

如果你想动态地使用dll ,你必须手动执行P/Invoke所做的相同操作:使用LoadLibrary/ GetProcAddress:

private static class UnsafeNativeMethods
{
    [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
    static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

    [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
    static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    [DllImport("kernel32", SetLastError=true)]
    static extern bool FreeLibrary(IntPtr hModule);
}
Run Code Online (Sandbox Code Playgroud)

你使用这样的:

显然我无法测试这个,因为我没有你的库,但它应该让你走上正轨.
为了简洁,我已经添加了故障检查,但你肯定应该添加这些.