【问题标题】:C# program call C# dllC# 程序调用 C# dll
【发布时间】:2018-02-27 06:54:51
【问题描述】:

我想用一个C# exe来动态加载由C#或C++构建的dll,C++ dll部分已经完成,但是C# dll还没有完成,因为exe在C# dll中找不到方法。

这是我将构建 CSharp.dll 的 C# dll 代码:

namespace NamespaceName
{
    public class ClassName
    {
        static public double MethodName(string input)
        {
            Console.WriteLine(input);
            Console.Read();
            return 0;
        }
    }
}

这是我的 C# exe 代码:

using System;
using System.Runtime.InteropServices;

namespace TestCall
{
    class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        static extern bool FreeLibrary(int hModule);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate double MethodName(string a);

        static void Main(string[] arg)  //pass in string array
        {
            string DllName = "...Desktop//CSharp.dll";                 //would be like: string  DllName = ChooseWhatDllToCall();
            string FuncName = "NamespaceName@ClassName@MethodName";    //would be like: string FuncName = ChooseWhatFuncToUse();
            int hModule = LoadLibrary(DllName);
            if (hModule == 0)
                return;
            IntPtr intPtr;
            intPtr = GetProcAddress(hModule, FuncName);
            if ((int)intPtr == 0)
            {
                FreeLibrary(hModule);
                return;
            }
            MethodName run = (MethodName)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(MethodName));
            string input = "just a string that will print by dll method";
            double result = run(input);
            FreeLibrary(hModule);
            return;
        }
    }
}

如果我正在加载 Cpp.dll,if ((int)intPtr == 0) 将为 false,加载 CSharp.dll 将为 true,所以我猜我需要将 string FuncName = "NamespaceName@ClassName@MethodName"; 编辑为其他内容。我该如何解决这个问题?

【问题讨论】:

  • 如果您想从 C# 代码加载 C# 库 - 使用适合此的方法(例如 Assembly.LoadFrom)。
  • 您可能想要.net 反射。我现在躺在床上,所以我不能做一个很好的链接。不过谷歌好:.net反射加载库
  • 如果您想对托管和非托管 DLL 使用相同的调用代码,那么您可以使用 UnmanagedExports。

标签: c# dll dllimport getprocaddress


【解决方案1】:

我现在回答我自己的问题,它可能并不完美,但它有效,感谢您的评论建议。

using System;
using System.Runtime.InteropServices;
using System.Reflection;

namespace TestCall   
{
    class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        static extern bool FreeLibrary(int hModule);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate double MyMethod(string a);

        static void Main(string[] arg) 
        {

            string DllName = "...Desktop\\CSharp.dll";  //or Cpp.dll
            string FuncName = "MyMethod";


            string input = "Just A String";


            int hModule = LoadLibrary(DllName); // you can build it dynamically 
            IntPtr intPtr = GetProcAddress(hModule, FuncName);
            if ((int)intPtr!=0 && hModule != 0)  //can I try this way?
            {                                    //                      Yes!
                MyMethod run = (MyMethod)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(MyMethod));
                double result = run(input);
                Console.WriteLine(result);
                Console.Read();
                FreeLibrary(hModule);
                return;
            }
            else                                 //No! 
            {
                FreeLibrary(hModule);

                                                 //so I try other way
                var DLL = Assembly.LoadFile(DllName);
                foreach (Type type in DLL.GetExportedTypes())
                {
                    var c = Activator.CreateInstance(type);
                    type.InvokeMember(FuncName, BindingFlags.InvokeMethod, null, c, new object[] { input });
                }
                return;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    相关资源
    最近更新 更多