简体   繁体   English

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

[英]Cant re-load C++ dll in C# Project

I hope there is someone there that can help me with loading and reloading a C++ dll into a C# project. 我希望那里有人可以帮助我将C ++ DLL加载和重新加载到C#项目中。

I am loading a C++ dll into my project using a file picker and then copying it to a file called Process.dll. 我正在使用文件选择器将C ++ DLL加载到我的项目中,然后将其复制到名为Process.dll的文件中。 I then use this dll to do its thing and then later I need the ability to load a new dll and for it to do its thing. 然后我使用这个dll来做它的事情然后我需要能够加载一个新的dll并让它做它的事情。

So it goes like this: 所以它是这样的:

  1. User picks a dll 用户选择一个DLL
  2. dll is copied to Processor.dll dll被复制到Processor.dll
  3. make my Processor class which uses dll import to make use of the dll 使用dll import的我的Processor类来使用dll
  4. Use the dll and call its various functions etc 使用DLL并调用其各种功能等
  5. Go back to 1. 回到1。

I have 2 classes 我有2节课

  1. ProcessTab - C# class that has the GUI and which calls the classes in ProcessPlugin ProcessTab - 具有GUI并在ProcessPlugin中调用类的C#类
  2. ProcessPlugin - C# class that calls the C++ classes, it uses dllImport etc ProcessPlugin - 调用C ++类的C#类,它使用dllImport等

The code looks like this: 代码如下所示:

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

Everything works fine and i call the methods in the C++ dll and get the expected outputs etc, but when I try to destroy it and reload it I get an error AccessViolationException was unhandled as shown in the comments in the code. 一切正常,我调用C ++ DLL中的方法并获得预期的输出等,但是当我尝试销毁它并重新加载它时,我得到一个错误AccessViolationException未处理,如代码中的注释所示。

Does anyone have any idea how I can solve this? 有谁知道如何解决这个问题?

Many thanks in advance 提前谢谢了

P/Invoke is not meant to handle this case. P / Invoke并不意味着处理这种情况。 It assumes the library never changes and I'm sure it doesn't expect you to call FreeLibrary on modules it imports. 它假设库永远不会改变,我相信它不会指望你在它导入的模块上调用FreeLibrary

If you want to use dlls dynamically , you'll have to manually do the equivalent of what P/Invoke does under the hood: use LoadLibrary / GetProcAddress : 如果你想动态使用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);
}

You use these like this: 你使用这样的:

  • Define a delegate: 定义委托:

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate ErrorCode ProcessorFunction(ref IntPtr pRx); 
  • Load the library: 加载库:

     IntPtr hLib = UnsafeNativeMethods.LoadLibrary("Processor.dll"); 
  • Get a delegate: 获得代表:

     IntPtr ctorPtr = UnsafeNativeMethods.GetProcAddress(hLib, "VE_ProcessorPluginLib_Rx_API_Constructor"); ProcessorFunction constructorFn = (ProcessorFunction)Marshal.GetDelegateForFunctionPointer(ctorPtr, typeof(ProcessorFunction)); 
  • Call it: 叫它:

     conctructorFn(ref pRxClass); 
  • When you're done, free the library (best in a finally block, SafeHandle or something to ensure this step is done): 完成后,释放库(最好在finally一个块, SafeHandle或其他东西,以确保完成此步骤):

     UnsafeNativeMethods.FreeLibrary(hLib); 
  • Then repeat all these steps for the second lib. 然后为第二个lib重复所有这些步骤。

Obviously I can't test this because I don't have your libs, but it should put you on the right track. 显然我无法测试这个,因为我没有你的库,但它应该让你走上正轨。
I've left adding the failure checks for brevity but you definitely should add these. 为了简洁,我已经添加了故障检查,但你肯定应该添加这些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM