首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • .net调用非托管dll,debug和release版本结果不同!
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-08-21 17:19:25 楼主
    vc++的dll函数原型如下,有三个:
    extern "C" _declspec(dllexport)
    int solution
    (char* roverfile,int iRoverModel,
    TOutputPt** vRes,
    bool bStatic=true);

    //设置基准站信息
    extern "C" _declspec(dllexport)
    void SetBaseInfo(
    char * strBaseFile,/*基准站绝对路径*/
    double B,
    double L,
    double H /*基准站BLH坐标*/
    );

    extern "C" _declspec(dllexport)
    void DestroyOutputPt (TOutputPt** vRes);

    我在.net里面调用改成了这样的:
    C# code
    [DllImport("USolution.dll")] // dll在磁盘中的存放位置 public static extern int [color=#FF0000]solution[/color](string roverfile, int iRoverModel, ref IntPtr vRes, bool bStatic); [DllImport("USolution.dll")] // dll在磁盘中的存放位置 //[DllImport(@"F:\“调查之星”后差分相关资料和说明\“调查之星”后差分相关资料和说明\USolution\Release\USolution.dll")] // dll在磁盘中的存放位置 public static extern void SetBaseInfo(string strBaseFile,double B,double L,double H); [DllImport("USolution.dll")] public static extern void DestroyOutputPt(IntPtr vRes);


    调用部分(主要是solution这个函数)
    C# code
    //解算 int iEpoches = -1; IntPtr vRes = new IntPtr(Marshal.SizeOf(typeof(TOutputPt))); iEpoches = solution(roverfile, 0, ref vRes, true); if (iEpoches >= 0) { //解算成功,将解算结果写入输出文件 TOutputPt[] pts = new TOutputPt[iEpoches]; IntPtr pt = vRes; for (int i = 0; i < iEpoches; i++) { pts[i] = (TOutputPt)Marshal.PtrToStructure(pt, typeof(TOutputPt)); pt = (IntPtr)((int)pt + Marshal.SizeOf(typeof(TOutputPt))); } InputToFile(pts,outfile); DestroyOutputPt(vRes);


    运行结果:
    在debug下面是对的,iEpoches 为一个正数,TOutputPt的vRes也有值
    但是在release下面,iEpoches为一个负数,这个负数在dll里面表示说“内存不足”

    这个错误搞了两天了,试了很多方法,但是仍然没有找到解决办法,望各位高手不宁赐教啊~小女子感激不尽!!
    60  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 17:22:101楼 得分:0
    注明:
    TOutputPt是结构体
    public struct TOutputPt
        {
            public double dGpsTime; //gps时间
            public double B;
            public double L;
            public double H;
            public double Fit; //越接近 0 代表解算精度越高
        }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wangdj2
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 17:52:252楼 得分:0
    太复杂了,看不懂。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • bbb16517
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 18:09:063楼 得分:0
    在函数调用过程中,所有调用信息(返回地址、参数)以及自动变量都是放在栈中的。若函数的声明与实现不同(参数、返回值、调用方式),就会产生错误————但 Debug 方式下,栈的访问通过 EBP 寄存器保存的地址实现,如果没有发生数组越界之类的错误(或是越界“不多”),函数通常能正常执行;Release 方式下,优化会省略 EBP 栈基址指针,这样通过一个全局指针访问栈就会造成返回地址错误是程序崩溃。C++ 的强类型特性能检查出大多数这样的错误,但如果用了强制类型转换,就不行了。你可以在 Release 版本中强制加入 /Oy- 编译选项来关掉帧指针省略,以确定是否此类错误。

    详细说明请访问http://hi.baidu.com/%D6%D9%C1%C1%C1%C1/blog/item/b3087b2591051e6635a80f55.html


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ttzyanswer
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 18:27:154楼 得分:0
    楼上的强.受教了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • LQknife
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 19:50:545楼 得分:0
    晓习 顶顶更健康
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • onthebox
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 08:37:486楼 得分:0
    我是来凑热闹的
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 10:33:407楼 得分:0
    bbb16517:
    你可以在 Release 版本中强制加入 /Oy- 编译选项来关掉帧指针省略,以确定是否此类错误。
    这个设置在vs.net哪里啊 没找到。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhangxuyu1118
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 10:57:558楼 得分:0
    TOutputPt加上#pragma pack(1) 
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dk385
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 11:00:069楼 得分:0
    是不是调用约定的问题,你把C++中的函数原型改成如下试试:
    C/C++ code
    extern "C" _declspec(dllexport)int __stdcall solution(char* roverfile,int iRoverModel, TOutputPt** vRes, bool bStatic=true);

    或者C#中的定义改成:
    C# code
    [DllImport("USolution.dll", CallingConvention = CallingConvention.Cdecl)] // dll在磁盘中的存放位置 public static extern int solution(string roverfile, int iRoverModel, ref IntPtr vRes, bool bStatic);
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wxjok
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 11:03:0010楼 得分:0
    在 Project\Settings... 中可以设置/Oy- 编译选项。
    你也可以像 Debug 一样调试你的 Release 版,只要加入调试符号。在 Project/Settings... 中,选中 Settings for "Win32 Release",选中 C/C++ 标签,Category 选 General,Debug Info 选 Program Database。再在 Link 标签 Project options 最后加上 "/OPT:REF" (引号不要输)。这样调试器就能使用 pdb 文件中的调试符号。但调试时你会发现断点很难设置,变量也很难找到——这些都被优化过了。
    具体请查看:http://www.builder.com.cn/2008/0706/964938.shtml
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 11:27:4311楼 得分:0
    zhangxuyu1118:
    加那个是什么意思啊?

    dk385:
    照你的说的改了,但是还是不行

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dk385
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 11:56:3512楼 得分:0
    把有关的C++代码也贴上来。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 12:04:2513楼 得分:0
    dk385:
    dll我没有源码
    只有一个vc++使用dll做的一个示例代码
    C/C++ code
    extern "C" _declspec(dllexport) int solution (char* roverfile,int iRoverModel, TOutputPt** vRes, bool bStatic=true); //设置基准站信息 extern "C" _declspec(dllexport) void SetBaseInfo( char * strBaseFile,/*基准站绝对路径*/ double B, double L, double H /*基准站BLH坐标*/ ); extern "C" _declspec(dllexport) void DestroyOutputPt (TOutputPt** vRes);


    我是要用C#调用这个dll做
    不晓得你要看的是不是这个?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lotus_dr
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 14:00:4814楼 得分:0
    up up up
    高手快来啊~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dk385
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 14:23:3315楼 得分:0
    单是这样很难判断问题出在那,
    你说在debug下面是对的,iEpoches 为一个正数,TOutputPt的vRes也有值
    是不是说调用没有问题,而且这里的代码调用完全正确?             
    C# code
    int iEpoches = -1; IntPtr vRes = new IntPtr(Marshal.SizeOf(typeof(TOutputPt))); iEpoches = solution(roverfile, 0, ref vRes, true); if (iEpoches >= 0) { //解算成功,将解算结果写入输出文件 TOutputPt[] pts = new TOutputPt[iEpoches]; IntPtr pt = vRes; for (int i = 0; i < iEpoches; i++) { pts[i] = (TOutputPt)Marshal.PtrToStructure(pt, typeof(TOutputPt));//这里也能取到正确的值? pt = (IntPtr)((int)pt + Marshal.SizeOf(typeof(TOutputPt))); } InputToFile(pts,outfile); DestroyOutputPt(vRes);



    但是在release下面,iEpoches为一个负数,这个负数在dll里面表示说“内存不足”.
    从你的代码看,dll里是申请了内存然后地址赋给传入的vRes变量的。 这步出错? 对比下你的C#项目中debug版本和Release版设置有什么不同?
    最好让DLL的开发者协助下,帮助解决问题。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • GhostAdai
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 09:22:3816楼 得分:0
    冲星,帮顶,接分!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zt_100094
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 09:33:0317楼 得分:0
    顶!
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved