【问题标题】:Calling a C# DLL in a C# program, entry point not found在 C# 程序中调用 C# DLL,找不到入口点
【发布时间】:2020-08-23 12:07:28
【问题描述】:

我正在使用以下 C# DLL。

    using System;

namespace LibraryTest
{
    public class Class1
    {
        public int callNr(int nr)
        {
            if (nr == 5)
            {
                return 555;
            }
            return 0;
        }
    }
}

并在程序中这样使用它:

    using System;
using System.Runtime.InteropServices;

namespace Builder.Store
{
    public class testIndicator : Indicator
    {
        [DllImport(@"C:\LibraryTest.dll", EntryPoint = "callNr")]
        public static extern int callNr(int nr);
        
        public override void Calculate()
        {
            int value = callNr(5);
            
            //do stuff...
        }
    }
}

唯一的结果是“无法在 DLL 中找到入口点”错误。 我的研究:我的VS里没有dumpbin,但是我用了dotPeek,结果是DLL与源代码匹配。 我使用了 Dependency Walker,DLL 似乎很好,但它没有指出入口点,附上截图。

https://i.stack.imgur.com/RR4UH.jpg

我使用的程序是一个独立的第三方软件,它允许自定义文件输入(我无法将 DLL 引用添加到实际程序中)。 我已经束手无策了。有任何指示和/或明显的错误吗?

【问题讨论】:

  • DllImport 用于 C 风格的导出函数(即本机代码)而不是 .NET (CIL+MD) 代码。如果 LibraryTest.dll 是 .NET 程序集 (DLL),则不要使用 DllImport,而是使用 Assembly.Load。 DependencyWalker 也只与原生相关
  • (尽管 C# 和 .NET 编译器输出的文件带有 .exe.dll 扩展名(也有格式良好的 Win32 PE 头文件),但它们与“本机”不同.exe 和 .dll 文件——它们(通常)不包含可直接执行的机器代码。从概念上讲,它们更像 Java 的 .jar 文件(因为它们是 .class 文件的容器,其中包含字节码和元数据)。

标签: c#


【解决方案1】:

如 cmets 中所述,DllImport 用于与本机代码交互。

要在 .NET Dll 中调用方法,您必须执行以下操作:

// First load the assembly
var assembly = Assembly.LoadFrom(@"C:\LibraryTest.dll");

// Get the type that includes the method you want to call by name (must include namespace and class name)
var class1Typetype = assembly.GetType("LibraryTest.Class1");

// Since your method is not static you must create an instance of that class.
// The following line will create an instance using the default parameterless constructor.
// If the class does not have a parameterless constructor, the following line will faile
var class1Instance = Activator.CreateInstance(class1Typetype);

// Find the method you want to call by name
// If there are multiple overloads, use the GetMethod overload that allows specifying parameter types
var method = class1Typetype.GetMethod("callNr");

// Use method.Invoke to call the method and pass the parameters in an array, cast the result to int
var result = (int)method.Invoke(class1Instance, new object[] { 5 });

这种按名称调用方法的技术称为“反射”。您可以在 Google 上搜索“C# 反射”一词,找到许多解释其工作原理的资源。

【讨论】:

  • 谢里夫,感谢您的时间和精力,这真的很有帮助,它有效!我有点打嗝,这些行不像 DllImport 那样进入类构造函数,但这很容易弄清楚。再次感谢您!
猜你喜欢
  • 2011-06-07
  • 2015-07-19
  • 2013-03-08
  • 2012-07-06
  • 2014-05-10
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
相关资源
最近更新 更多