簡體   English   中英

C#程序在C DLL中找不到函數

[英]C# program doesn't find function in C DLL

我遇到一個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>

根據您的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)]

編輯(2015年10月26日):

仔細檢查.def文件中的語法,並確保.def文件已添加到解決方案中,並在鏈接器設置下列為模塊定義文件 這是一個簡短的例子,表明這確實有效:

  1. 我創建了一個帶有單個源文件的新解決方案(Win32 DLL)(Example.c):
#include <Windows.h>

__declspec(dllexport) int __stdcall ExampleFunction(int param1, int param2)
{
    return 0;
}
  1. 我構建了解決方案,然后在生成的ExampleDll.dll上運行dumpbin 結果如下(顯示裝飾名稱):
Dump of file ExampleDll.dll

File Type: DLL

  Section contains the following exports for ExampleDll.dll

    00000000 characteristics
    562E5A83 time date stamp Mon Oct 26 12:53:23 2015
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 0001100F _ExampleFunction@8 = @ILT+10(_ExampleFunction@8)
  1. 我增加了以下DEF文件(Example.def)到我的解決方案,然后雙重檢查該文件被列為該項目的設置(鏈接,輸入,模塊定義文件) 模塊定義文件
LIBRARY ExampleDll
EXPORTS
    ExampleFunction
  1. 最后,我重新構建了然后在新的ExampleDll.Dll上重新運行dumpbin (顯示名稱修飾已被刪除):
Dump of file ExampleDll.dll

File Type: DLL

  Section contains the following exports for ExampleDll.dll

    00000000 characteristics
    562E5CBF time date stamp Mon Oct 26 13:02:55 2015
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 0001100F ExampleFunction = @ILT+10(_ExampleFunction@8)

關於在C#代碼中向[DllImport]添加CallingConvention的問題,請仔細檢查語法。 如果沒有明顯錯誤,請將您的代碼與錯誤消息一起發布。

這有效:

1)刪除#define CALL_TYPE __stdcall

2)將“,CallingConvention = CallingConvention.Cdecl”添加到DLLImport

3)不要使用.DEF文件

它的工作原理是因為cdecl沒有裝飾: https ://msdn.microsoft.com/en-us/library/vstudio/x7kb4e2f( v = vs.100).aspx

我在我的示例代碼和我的實際代碼中測試了這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM