c#程序在DLL中找不到函数

本文关键字:找不到 函数 DLL 程序 | 更新日期: 2023-09-27 18:19:08

我有一个c#程序在C DLL中调用函数的问题。我使用VS 2015。

第一次调用XBaseResolveAll工作,但调用XBaseSeek会导致弹出这样的提示:

An unhandled exception of type 'System.EntryPointNotFoundException' occurred in Call_C.exe
Additional information: Unable to find an entry point named 'XBaseSeek' in DLL 'W:'C_sharp'Call_C'Debug'C_dll.dll'.

请注意,dll的dumpbin显示所有函数都已按预期导出。如下所示:

我已经尝试搜索,但没有发现这个问题讨论。所以我一定是做了什么蠢事,只是我没看到而已。我创建了一个小示例来说明这个问题。

有人能帮忙吗?

下面是示例文件:

----------
Program.cs
----------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using XBaseNamespace.SecondNamespace;

namespace Call_C
{
    class Program
    {
        static void Main()
        {
            XBaseFunctions.XBaseResolveAll();
            XBaseFunctions.XBaseSeek(UIntPtr.Zero, 0, 0);
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }
}
-----------------
XBaseNamespace.cs
-----------------
//  XBase functions
using System;
using System.Runtime.InteropServices;
namespace XBaseNamespace.SecondNamespace
{
    class XBaseFunctions
    {
        [DllImport("W:''C_sharp''Call_C''Debug''C_dll.dll", CharSet = CharSet.Ansi)]
        public static extern int XBaseResolveAll();
        [DllImport("W:''C_sharp''Call_C''Debug''C_dll.dll", CharSet = CharSet.Ansi)]
        public static extern int XBaseSeek(UIntPtr myhandle, long offset, int origin);
    }
} 
-------
c_dll.c
-------
//  C DLL experiment
#include <stdio.h>
#define DSI_DLL __declspec(dllexport)
#define CALL_TYPE __stdcall
DSI_DLL int CALL_TYPE XBaseResolveAll()
{
    return 0;
}

DSI_DLL int CALL_TYPE XBaseSeek(unsigned int *handle, long offset, int origin)
{
    return 0;
}
---------------
Output of build
---------------
1>------ Rebuild All started: Project: C_dll, Configuration: Debug Win32 ------
1>  c_dll.c
1>     Creating library W:'C_sharp'Call_C'Debug'C_dll.lib and object W:'C_sharp'Call_C'Debug'C_dll.exp
1>  C_dll.vcxproj -> W:'C_sharp'Call_C'Debug'C_dll.dll
2>------ Rebuild All started: Project: Call_C, Configuration: Debug Any CPU ------
2>  Call_C -> W:'C_sharp'Call_C'bin'Debug'Call_C.exe
========== Rebuild All: 2 succeeded, 0 failed, 0 skipped ==========
-----------------------
output from dumbbin.exe
-----------------------
C:'Program Files (x86)'Microsoft Visual Studio 11.0'Common7'IDE>"C:'Program Files (x86)'Microsoft Visual Studio 11.0'VC'bin'dumpbin.exe" /exports "W:'C_sharp'Call_C
'Debug'C_dll.dll"
Microsoft (R) COFF/PE Dumper Version 11.00.60610.1
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file W:'C_sharp'Call_C'Debug'C_dll.dll
File Type: DLL
  Section contains the following exports for C_dll.dll
    00000000 characteristics
    562D7696 time date stamp Sun Oct 25 20:40:54 2015
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names
    ordinal hint RVA      name
          1    0 00011028 _XBaseResolveAll@0 = @ILT+35(_XBaseResolveAll@0)
          2    1 00011082 _XBaseSeek@12 = @ILT+125(_XBaseSeek@12)
  Summary
        1000 .00cfg
        1000 .data
        1000 .idata
        2000 .rdata
        1000 .reloc
        1000 .rsrc
        5000 .text
       10000 .textbss
C:'Program Files (x86)'Microsoft Visual Studio 11.0'Common7'IDE>

c#程序在DLL中找不到函数

根据您的dumpbin输出,DLL导出表中的函数名已被"修饰"以包含有关参数数量的信息。你需要禁用名称修饰,或者在c#代码中的DllImport中使用修饰过的名称。就我个人而言,我会禁用姓名装饰。您可以通过在DLL项目中创建模块定义文件(.def)并列出导出的函数名来禁用导出函数的名称修饰。例子:

LIBRARY C_dll
EXPORTS
    XBaseResolveAll
    XBaseSeek

同样,在你的c#代码中包括调用约定作为DllImport的一部分:

[DllImport("W:''C_sharp''Call_C''Debug''C_dll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

编辑(10/26/2015):

仔细检查.def文件中的语法,并确保.def文件已添加到解决方案中,并在链接器设置下列为模块定义文件。下面是一个简单的例子来说明这是可行的:

    我创建了一个新的解决方案(Win32 DLL)与一个单一的源文件(示例.c):
<>之前# include & lt; Windows.h>__declspec(dllexport) int __stdcall ExampleFunction(int param1, int param2){返回0;}之前
  • 我构建了解决方案,然后在得到的ExampleDll.dll上运行dumpbin。结果如下所示(显示已修饰的名称):
  • <>之前转储ExampleDll.dll文件文件类型:DLL节包含ExampleDll.dll的以下导出00000000特点562E5A83时间日期戳星期一Oct 26 12:53:23 20150.00版本序数基1 .函数数1个名字序数提示RVA名称10 0001100F _ExampleFunction@8 = @ILT+10(_ExampleFunction@8)之前
  • 我添加了以下.def文件(Example.def)到我的解决方案,然后仔细检查该文件被列为模块定义文件在项目设置(链接器,输入,模块定义文件)。<>之前图书馆ExampleDll出口ExampleFunction之前
  • 最后,我重建,然后重新运行dumpbin在新的ExampleDll.Dll(显示名称装饰已被删除):
  • <>之前转储ExampleDll.dll文件文件类型:DLL节包含ExampleDll.dll的以下导出00000000特点562E5CBF时间戳星期一10月26日13:02:55 20150.00版本序数基1 .函数数1个名字序数提示RVA名称10 0001100F ExampleFunction = @ILT+10(_ExampleFunction@8)之前

    关于在c#代码中将CallingConvention添加到[DllImport]的问题,请仔细检查您的语法。如果没有明显的错误,则将代码与错误消息一起发布。

    这行得通:

    1)删除#define CALL_TYPE __stdcall

    2)添加",CallingConvention = CallingConvention"。

    3)不要使用。def文件

    它可以工作,因为cdecl不修饰:https://msdn.microsoft.com/en-us/library/vstudio/x7kb4e2f(v=vs.100).aspx

    我在我的示例代码和实际代码中测试了这一点。