使用包含动态加载的dll本身的动态加载的dll

时间:2015-07-06 09:00:20

标签: c# dynamic dll plugins

简介

我的程序允许其他开发人员编写插件。这些插件(是dll文件)放在某个目录中,我的程序能够在运行时加载它们,如下所示:

Assembly assembly = Assembly.LoadFrom("MyPluginPath");
object Plugin = assembly.CreateInstance("Plugins.Main", true);

然后程序将能够以这种方式从插件中调用main方法:

var pluginType = Plugin.GetType();
var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param});

这对我到目前为止所写的所有插件都有效,这些插件遵循以下特定结构:

namespace Plugins
{
    public class Main : IDisposable
    {
        public Bitmap MyInternalMethod(Bitmap param)
        {
             // method body
        }
    }
}

问题

现在有一个我要编写的新插件,它在运行时加载外部dll:

namespace Plugins
{
    public class Main : IDisposable
    {
        [System.Runtime.InteropServices.DllImport("MyExternalDLL.dll")]
        unsafe private static extern int Initialize(int* arg1, char* arg2);

        public Bitmap MyInternalMethod(Bitmap param)
        {
             // method body
             Initialize(x,y);
        }
    }
}
上面代码中的

Initialize(x,y)方法给出了一个错误,上面写着

  

无法初始化com库。

备注

  1. 我为我的插件创建了一个可执行的测试应用程序,它工作正常,所以我知道在运行时将它用作dll时会出现问题。
  2. 我想也许我应该在主程序中加载我的外部dll,然后将它作为Func<>对象传递给我的插件,但Func<>不允许指针变量(Initialize方法包含int*char*等参数,即使它确实存在,我也不确定这个解决方案是否会起作用。
  3. 我尝试使用winApi作为“Sinatr”在评论中建议按照this回答,但错误仍然存​​在。我甚至尝试使用MyExternalDLL.dll在主程序中加载winApi并将检索到的Initialize方法地址传递给我的插件,如下面的代码,但错误保持不变(这种方式错误发生在func(x,y)):
  4. 主程序:

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr LoadLibrary(string name);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string name);
    
        IntPtr dllHandle = IntPtr.Zero;
        IntPtr addr = IntPtr.Zero;
    
        private void RunPlugin()
        {
            dllHandle = LoadLibrary("MyExternalDLL.dll");
            addr = GetProcAddress(dllHandle, "Initialize");
            var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param, addr});
        }
    

    插件:

        public class Main : IDisposable
        {
            private unsafe delegate byte initialize_api(int* arg1, char* arg2);
    
            public Bitmap MyInternalMethod(Bitmap param, IntPtr addr)
            {
                // method body
                //initialize_api is a delegate with the same signature as Initialize(x,y); 
                var func = (initialize_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(initialize_api));
                func(x,y);
            }
        }
    
    1. 由于我们在这里谈论插件,我不认为实现我的程序和插件都可以使用的公共Interface
    2. 问题

      是否甚至可以像我描述的那样使用包含动态加载的dll的动态加载的dll?如果是的话,我该怎么做才能使这项工作?

0 个答案:

没有答案