简体   繁体   中英

C# program doesn't find function in C DLL

I am having a problem with a C# program that calls functions in a C DLL. I'm using VS 2015.

The first call to XBaseResolveAll works but the call to XBaseSeek causes a popup saying this:

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'.

Note that a dumpbin of the dll shows all functions to have been exported as expected. See the output below.

I have tried searching but have not found this problem discussed. So I must be doing something stupid but I just don't see it. I have created a small sample that illustrates the problem.

Can someone help?

Below are the sample files:

----------
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>

Based on your dumpbin output, the function names in the DLL export table have been "decorated" to include information about the number of parameters. You will need to either disable the name decoration, or use the decorated names in your DllImport within the C# code. Personally, I would disable name decoration. You can disable the name decoration for your exported functions by creating a module definition file (.def) in your DLL project and listing the exported function names. Example:

LIBRARY C_dll
EXPORTS
    XBaseResolveAll
    XBaseSeek

Also, in your C# code include the calling convention as part of the DllImport:

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

Edit (10/26/2015):

Double check the syntax in your .def file, and make sure the .def file has been added to the solution and is listed as the Module Definition File under Linker settings. Here is a brief example to show that this does work:

  1. I created a new solution (Win32 DLL) with a single source file (Example.c):
#include <Windows.h>

__declspec(dllexport) int __stdcall ExampleFunction(int param1, int param2)
{
    return 0;
}
  1. I built the solution, then ran dumpbin on the resulting ExampleDll.dll. The result looks like this (showing decorated names):
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. I added the following .def file (Example.def) to my solution and then double checked that the file is listed as Module Definition File in the project settings (Linker, Input, Module Definition File).
LIBRARY ExampleDll
EXPORTS
    ExampleFunction
  1. Finally, I rebuilt and then re-ran dumpbin on the new ExampleDll.Dll (showing that name decoration has been removed):
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)

Regarding the issue with adding CallingConvention to your [DllImport] in your C# code, double check your syntax. If nothing is obviously wrong, post your code along with the error message.

This works:

1) Remove the #define CALL_TYPE __stdcall

2) Add ", CallingConvention = CallingConvention.Cdecl" to the DLLImport

3) Don't use the .DEF file

It works because cdecl does not decorate: https://msdn.microsoft.com/en-us/library/vstudio/x7kb4e2f(v=vs.100).aspx

I tested this in my sample code and also in my real code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM