- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在使用 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 的转储文件显示所有函数都已按预期导出。请参阅下面的输出。
我试过搜索但没有发现讨论过这个问题。所以我一定是在做一些愚蠢的事情,但我只是没有看到它。我创建了一个小样本来说明问题。
有人可以帮忙吗?
下面是示例文件:
----------
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)]
编辑(10/26/2015):
仔细检查 .def 文件中的语法,并确保 .def 文件已添加到解决方案中并在链接器设置下列为模块定义文件。下面是一个简单的例子来证明这确实有效:
#include <Windows.h>__declspec(dllexport) int __stdcall ExampleFunction(int param1, int param2){ return 0;}
dumpbin
。结果如下所示(显示经过修饰的名称):Dump of file ExampleDll.dllFile 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)
LIBRARY ExampleDllEXPORTS ExampleFunction
dumpbin
(显示名称修饰已被删除):Dump of file ExampleDll.dllFile 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)
关于将 CallingConvention
添加到 C# 代码中的 [DllImport]
的问题,请仔细检查您的语法。如果没有明显错误,请将您的代码与错误消息一起发布。
关于C# 程序在 C DLL 中找不到函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33336892/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!