导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/5 11:29:26
标题:
delphi调用c++ dll 的问题
浏览:796
加入我的收藏
楼主:
最近在学机器视觉halcon 因为要与delphi开发的系统交互,想直接调用halconcpp.dll,但是导出函数名的问题调用不成功,通过二次封装成halconpas.dll, 但是delphi调用某些函数会报错,做了一个最简单的测试,用c++程序能调用成功,但delphi调用失败,不知为何,求大师指点一二。 二次封装测试的dll c++代码TestDll.cpp: #include "TestDll.h" #include "Halcon.h" #include "HalconCpp.h" #include "HDevThread.h" using namespace HalconCpp; void __stdcall TestShowImage(int hwnd) { #if defined(_WIN32) SetSystem("use_window_thread", "true"); #endif SetHcppInterfaceStringEncodingIsUtf8(false); SetSystem("width", 512); SetSystem("height", 512); HObject ho_Image_display; HTuple hv_imageWidth, hv_imageHeight, hv_WindowHandle1; if (HDevWindowStack::IsOpen()) CloseWindow(HDevWindowStack::Pop()); ReadImage(&ho_Image_display, "E:/PyQtProjects/halcon_vcl_test/data/display.jpg"); GetImageSize(ho_Image_display, &hv_imageWidth, &hv_imageHeight); SetWindowAttr("background_color","black"); OpenWindow(0,0,hv_imageWidth,hv_imageHeight,0,"visible","",&hv_WindowHandle1); HDevWindowStack::Push(hv_WindowHandle1); if (HDevWindowStack::IsOpen()) DispObj(ho_Image_display, HDevWindowStack::GetActive()); } h文件TestDll.h: #ifndef TestDLL_H #define TestDLL_H #endif #ifdef __cplusplus extern"C"{ #endif __declspec(dllexport) void __stdcall TestShowImage(int hwnd); #ifdef __cplusplus } #endif
----------------------------------------------
-
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/5 11:33:08
1楼:
C++ 调用 程序: # include <stdlib.h> # include "TestDll.h" extern "C" __declspec(dllimport) void __stdcall TestShowImage(int hwnd); int main(int argc, char *argv[]) { TestShowImage(0); system("pause"); } delphi 调用 代码: procedure TestShowImage(PWinHandle: Integer); cdecl; stdcall; external 'TestDll.dll' name 'TestShowImage'; procedure TForm1.Button1Click(Sender: TObject); begin TestShowImage(0); end; C++ 调用程序运行没问题,但是delphi调用会报错 Invalid floating point operation 出错的代码在dll里最后一行的 DispObj(); 不知怎么处理,才能使delphi调用能正常。
----------------------------------------------
-
作者:
2023/6/5 12:07:01
2楼:
procedure TestShowImage(PWinHandle: Integer); cdecl; stdcall; 这里的cdecl去掉? 它和stdcall是完全不同的调用方式, 写一起似乎就乱套了
----------------------------------------------
-
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/5 13:49:48
3楼:
去掉 cdecl 或 去掉 stdcall 都是一样, 但c++的程序就没问题
----------------------------------------------
-
作者:
2023/6/6 12:16:40
4楼:
1:cdecl和stdcall不能同时用 2:导出表用def定义
----------------------------------------------
--
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/6 14:55:03
5楼:
问题已解决 参考网上的方法,在delphi主窗体OnCreate事件中加入 Set8087CW($133f) 问题依旧 参考 https://www.codercto.com/a/9819.html 在DLL代码TestDll.cpp中加入下列代码: #include "float.h" int old_fpcw = _controlfp(0,0) _controlfp(MCW_EM, MCW_EM); ...... _controlfp(old_fpcw, _MCW_DN | _MCW_EM |_MCW_RC ) Delphi调用正常 有没有办法不修改TestDll.cpp,只修改delphi程序,能解决此问题?
----------------------------------------------
-
作者:
2023/6/7 10:01:16
6楼:
dll加载之前尝试Set8087CW ?
----------------------------------------------
-
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/8 8:24:00
7楼:
dll加载之前Set8087CW 也是一样,主程序和dll都是64位的
----------------------------------------------
-
作者:
2023/6/8 12:33:16
8楼:
64位下要用SetMXCSR,不是Set8087CW,可以参考 System.SysUtils.pas 里这一段代码 const // 8087 control word // Infinity control = 1 Affine // Rounding Control = 0 Round to nearest or even // Precision Control = 3 64 bits // All interrupts masked CWNear: Word = $133F; {$ENDIF CPUX86} {$IFDEF CPUX64} const // MXCSR control word // Rounding Control = 0 Round to nearest or even // All interrupts masked MXCSRNear: UInt32 = $1F80; {$ENDIF CPUX64} .......... .......... .......... {$IFDEF CPUX86} { Prepare the FPU } LSavedCtrlWord := Get8087CW(); TestAndClearFPUExceptions(0); Set8087CW(CWNear); {$ENDIF CPUX86} {$IF Defined(CPUX64)} { Prepare the FPU } LSavedMXCSR := GetMXCSR; TestAndClearSSEExceptions(0); SetMXCSR(MXCSRNear); {$ENDIF Defined(CPUX64)}
----------------------------------------------
-
作者:
2023/6/8 15:11:21
9楼:
https://stackoverflow.com/questions/19187479/masking-floating-point-exceptions-with-set8087cw-setmxcsr-and-twebbrowser 老外好像吐槽这玩意来着 。
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
denis (Denis)
★☆☆☆☆
-
盒子活跃会员
2023/6/9 8:10:51
10楼:
按8楼的方法可行,谢谢各位,问题完美解决
----------------------------------------------
-