C++使用 void extern __declspec(dllexport) 函数名()定义的输出函数, 在C#中调用时, 如前文所述, 使用
[DllImport("D:\VS2005Projects\Dev_PetroSim2010b\Dev_AMDBR\Debug\Dev_DR_AMDBR.dll", EntryPoint = "#1")]
public static extern void amDBRSurfaceTensionEX(int compCount, int[]
components, int modelID, [MarshalAs(UnmanagedType.LPArray,
SizeParamIndex = 1)] double[] Z, ref int errorID);
来调用.

这里注意的是,定义函数入口点的参数EntryPoint = "#1", C#中有2种方式可以定义入口点,
一种是以序号加前缀"#",这是我一直用的,另一种是用EntryPoint="函数名",这种方法我试了很多次却无法实现,C#编译器总会说在DLL中
没有找到函数.

如何找到函数所对应的EntryPoint编号呢?我用的是一个叫DLLExportViewer的软件,可以告诉你各个函数的Ordinal,即
编号,照此调用即可,但是问题是,如果原DLL进行编辑之后,增加或减少输出函数之后,各个函数的编号会重新打乱,使原程序无法进行.所以对这种情况,即
DLL尚在编辑之中时,还是以函数名作为EntryPoint比较好.

在C:Program FilesMicrosoft Visual Studio 8VCbin目录中,有一个文件dumpbin.exe文件和DLLExportViewer一样可以查看DLL的输出函数,但是在运行时,居然跳出一个错误窗口
查找后发现,mspdb80.dll文件是在C:Program FilesCommon FilesMicrosoft
SharedVSA8.0VsaEnv中,将此文件复制到C:Program FilesMicrosoft Visual Studio
8VCbin目录,再运行时错误消失.

查阅dumpbin的输出,发现输出函数说明及如下

ordinal hint RVA name
7 6 0002D591 ?amDBRSurfaceTensionEX@@YAXHPAHHPANAAH@Z = @ILT+1420(?amDBRSurfaceTensionEX@@YAXHPAHHPANAAH@Z)
 

前面的ordinal 7即为函数的输出序号, name列即为可用的函数名,在C#中,改函数声明为如下即可用函数名作为EntryPoint

[DllImport("D:VS2005ProjectsDev_PetroSim2010bDev_AMDBRDebugDev_DR_AMDBR.dll",
EntryPoint = "?amDBRSurfaceTensionEX@@YAXHPAHHPANAAH@Z")]

============================================

照上述做法,导出函数可以成功,但是在C#中调用却是相当麻烦,因为函数的入口名称太过繁杂且不可理解,因此,还是要解决在C++中的函数输出,以使在C#中能直接以函数名作为入口.

上述问题中,实际上是在C++中函数输出时,默认输出名是使用C++的mangled name, 要使用C的命名方式方可直接使用其输出名,这时,函数输出声明应改为如下:
extern "C" __declspec(dllexport) void amDBREnthalpyEX(int CompCount,
int* streamComp, int modelID, double* streamInfo, int& errorID)

这样,可以看到DLLExportViewer的查看结果了,以此方式声明的amDBREnthalpyEX函数和以原方式声明的其他函数的名称的不同如下图所示.

这时,在C#中,就可以以函数名称作为入口点了:
[DllImport("D:VS2005ProjectsDev_PetroSim2010bDev_AMDBRDebugDev_DR_AMDBR.dll", EntryPoint = "amDBREnthalpyEX")]
public static extern void amDBREnthalpyEX(int compCount, int[]
components, int modelID, [MarshalAs(UnmanagedType.LPArray,
SizeParamIndex = 1)] double[] Z, ref int errorID);

C#调用C++函数入口点的问题 z的更多相关文章

  1. 可执行程序的入口点在那里?(强化概念:程序真正的入口是mainCRTstartup)

    今天终于有时间来研究一下一个很大很大的工程编译成一个exe和若干dll后,程序是如果执行它的第一条指令的?操作系统以什么规则来找到应该执行的第一条指令(或说如何找到第一个入口函数的)? 我们以前写wi ...

  2. vs/windows程序找不到入口点cuvidGetDecodeStatus于AppDecGL.exe动态链接库上

    解决方法:这个问题的原因是由于使用的英伟达显卡驱动版本不够新,更新显卡驱动即可. 找了一个多月的原因,终于知道起源了.最终问题还是出在了nvcuvid.lib/.dll上面.通过分析vs调试信息可以得 ...

  3. C# 互操作性入门系列(二):使用平台调用调用Win32 函数

    好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...

  4. [转]C# 互操作性入门系列(二):使用平台调用调用Win32 函数

    传送门 C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列(二):使用平台调用调用Win32 函数 C# 互操作性入门系列(三):平台调用中的数据封送处理 ...

  5. 如何为WPF添加Main()函数 程序入口点的修改

    一般的.WPF的Main()函数是自动生成的,不过有时候我们需要为我们的应用程序传参.那么自动生成的Main()函数就不会满足我们的要求. 那么如何为WPF Application 设置Main()函 ...

  6. 在纯C工程的main函数之前跑代码(手工找到程序入口点, 替换为我们自己的函数)

    在main函数之前跑代码的方法 方法: 手工找到程序入口点, 替换为我们自己的函数 写测试程序 // test.cpp : Defines the entry point for the consol ...

  7. (转) MFC的入口点与消息循环,消息映射

    博文分析的很不错,尤其是替换默认窗口过程的这块,本人觉得,所有的这些都可以参阅侯杰的<深入浅出MFC >. 来自:http://blog.csdn.net/sryan/article/de ...

  8. Android程序的入口点

    原文:Android程序的入口点 android应用程序,由一到多个Activity组成.每个Activity没有很紧密的联系,因为我们可以在自己的程序中调用其它Activity,特别是调用自己的代码 ...

  9. 逆向课程第二讲,寻找main入口点

    逆向课程第二讲,寻找main入口点 一丶识别各个程序的入口点 入门知识,识别各个应用程序的入口点 (举例识别VC 编译器生成,以及VS编译生成的Debug版本以及Release版本) 1.识别VC6. ...

随机推荐

  1. hdu 5000 Clone

    dp,用dp[i][j],表示和为i的前j个维度的种类.其中arr[i],表示第i维的最大值. 则\begin{equation} dp[i][j] = \sum_{0 \leq k \leq \mi ...

  2. LinqToExcel常用对象

    1.ExcelQueryFactory对象(1)获取工作表名集合IEnumerable<string> GetWorksheetNames() //获取工作薄中的工作表名 foreach ...

  3. apache 工作模式

    apache三种工作模式: prefork(2.4前默认)/worker/event(2.4默认)内容整理来自以下网站http://m.blog.csdn.net/article/details?id ...

  4. 实现一个div在浏览器水平居中

    第一种方法: div { margin: 0 auto; width: 960px; } 第二种方法(兼容IE): body { text-align: center; } div { margin: ...

  5. JQuery 绑定事件时传递参数的实现方法

    如题,比如我想在$(":text").bind("keyup",funcionName);将当前的文本框作为参数传递给 functionName所代表的函数,应 ...

  6. php使用phpmailer发送邮件

    本人新手,由于要做邮件发送验证码,所以找到和搜集到这些,本人亲测完全可以用 这是163邮箱的   因为不是企业邮箱填写的账号是163的账号,但是密码是授权码 授权码的获取方式为:

  7. 【小知识】DataTable 转 List -----------点滴之水,汇涓涓细流,成汪洋大海

    在大部分时候我们从ADO中得到的数据都是DataTable.DataSet数据源,然而有强迫症的同学老是喜欢折腾,硬是要把它转换为实体集合,说是DataTable效率差云云,于是乎收到了同化. 必要信 ...

  8. E8.NET工作流平台如何与其他软件系统集成?

    1.与邮件系统集成 E8.Net工作流开发架构已经提供了与电子邮件系统集成的模块,可以轻松实现与EXCHANGE等专业邮件系统集成的应用需求. 2.与短信系统集成 E8.Net工作流架构已经提供了手机 ...

  9. MJRefreshFooterView

    实例化header和footer _header = [MJRefreshHeaderView header]; _header.scrollView = _tableView; 设置header和f ...

  10. Oracle job procedure

    Oracle job procedure 存储过程定时任务 oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务. 一.查询系统中的job,可以查询视图 --相关视图 ...