【问题标题】:Linking Functions In a C# DLL from a C# Application从 C# 应用程序链接 C# DLL 中的函数
【发布时间】:2010-10-26 15:16:26
【问题描述】:

从 C# 应用程序链接到 C# DLL 中的函数的正确方法是什么?

这是我的 DLL 的外观:

namespace WMIQuery_Namespace
{
    public class WMIQuery
    {
        public static string GetPortName()
        {
            /* Does some stuff returning valid port name. */

            return string.Empty;
        }

        public static int ScanForAdapters()
        {
            /* Does some stuff returning valid adapter index. */

            return _index = -1;
        }
    }
}

这是我的应用程序界面的外观:

namespace MyApp_Namespace
{
    class MyApp_Class
    {
        internal static class WMIQuery
        {
            [DllImport("WMIQuery.dll")]
            internal static extern string GetPortName();

            [DllImport("WMIQuery.dll")]
            internal static extern int ScanForAdapters();
        }
    }
}

一切都编译时没有任何错误或警告,但是当我尝试从我的应用程序调用这些函数时,会抛出此异常:

"找不到名为的入口点 DLL 中的“ScanForAdapters” 'WMIQuery.dll'。”

我做错了什么?我知道我可以添加 WMIQuery 作为参考,但我需要将其链接为非托管 DLL。谢谢。

【问题讨论】:

  • 必须链接它,还是可以将 DLL 引用导入到 Visual Studio 项目中?
  • @Daniel:为了清楚起见,我更新了问题。它需要被链接。
  • 如果你能解释为什么你不想添加WMIQuery作为参考,这将更容易回答。
  • 不是直接的答案,但如果您阅读Portable Executable 格式(Windows 上的 EXE 和 DLL 文件的文件格式)以及如何使用a .NET Assembly DLL that you create with C# is different from a vanilla PE DLL,事情可能会更清楚。 P/Invoke 适用于普通 PE DLL;要调用 .NET 程序集 DLL 中的方法,您需要使用 .NET 机制。
  • @Daniel:谢谢,这有点帮助。

标签: c# .net dll


【解决方案1】:

如果 DLL 是 C# DLL,则不要使用 P/Invoke 来“链接”到它。

只需将其添加为对您的项目的引用,然后在您要使用它的类的顶部添加:

using WMIQuery_Namespace;

你可以直接这样做:

var port = WMIQuery.GetPortName();

“客户端”端根本不需要任何代码...


至于:

但应用程序的要求要求它在运行时动态加载。谢谢。

意识到直到您的应用程序使用它的时间点才会加载程序集。 CLR 中的程序集不会在启动时加载,而是在从程序集中使用第一种类型时加载。无需尝试通过 P/Invoke 加载来实现后期绑定。

如果您不信任这一点,您始终可以使用Assembly.Load 和反射来调用成员,但平台调用服务将无法加载 C# 程序集。

【讨论】:

  • 我在问题中特别提到了应用程序的需求要求它在运行时动态加载; WMIQuery不能作为引用添加,这是实现using WMIQuery_Namespace所必需的。
  • @Jim:在实际使用第一种类型之前不会加载程序集......添加引用不会违反您的要求。
  • @Jim:我还在这里为您提供了唯一的其他真正选择 - P/Invoke 不适用于 .NET 程序集。
  • @Jim:C++ 应用程序无法链接到 C# dll - 它可以将其添加为引用并使用 C++/CLI,或者它可以托管 CLR,或者它可以使用 COM。它不能像使用原生 DLL 一样使用 LoadLibrary/FreeLibrary。
  • @Jim Fell:C++ 只能加载 C# DLL,前提是它是托管 C++(即 C++/CLI,在 .NET Framework 下运行)。非托管 C++ 代码可以从 C# DLL(即 .NET 程序集)加载类的唯一方法是使用 COM 互操作并创建 COM 实例。然后 COM 互操作基础结构将加载 .NET Framework。基本上,C# 代码被编译为 CLR 字节码,没有运行的 CLR 实例就无法执行;编译为本机的 C++ 没有运行的 CLR 实例。要在这两个世界之间进行交流,您需要以某种方式弥合这一差距。
【解决方案2】:

这是否满足您的需求?

http://www.codeproject.com/KB/cs/csharpreflection.aspx

克里斯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多