使用 Delphi 中的 C++ DLL 时的 AccessViolation [英] AccessViolation when using C++ DLL from Delphi

查看:11

问题描述

我在尝试使用 Delphi (Turbo Delphi 2006) 程序中用 C++ 编写的 DLL 时遇到了一个奇怪的问题.

I have a weird problem trying to use a DLL written in C++ from a Delphi (Turbo Delphi 2006) program.

当我从命令行运行 Delphi 程序(见下文)时,一切正常.另外,当我在没有调试的情况下从 Delphi 环境运行它(CTRL+SHIFT+F9)时,一切都很好.但是,当运行它调试(F9)时,我收到以下错误:

When I run the Delphi program (see below) from the command line, everything works fine. Also, when I run it from the Delphi environment without debugging (CTRL+SHIFT+F9), everything is fine. However, when running it with debugging (F9), I get the following error:

项目 Z: est.exe 出现故障消息:'访问冲突在0x00403fdf:读取地址0x00a14e74'.进程停止.使用步骤或运行以继续.

Project Z: est.exe faulted with message: 'access violation at 0x00403fdf: read of address 0x00a14e74'. Process stopped. Use Step or Run to continue.

奇怪的是,错误发生在执行最后一个结束"时.的代码.Delphi 的 CPU 显示说这是在UnsetExceptionHandler"中的某处,在FinalizeUnits"之前的四行,更具体地说,在

The weird thing is that the error occurs on executing the last 'end.' of the code. Delphi's CPU display says this is somewhere in 'UnsetExceptionHandler', four lines before 'FinalizeUnits', to be more specific, at

00403FDF 3901 cmp [ecx],eax

00403FDF 3901 cmp [ecx],eax

我有点不知所措;Delphi 不是我的领域(我是编写 DLL 的人,现在我需要提供一个使用它的示例程序).因此,非常感谢有关此问题的任何帮助:)

I'm somewhat at a loss here; Delphi is not my domain (I was the one writing the DLL, and now I need to provide an example program using it). So any help on this issue is greatly appreciated :)

这是德尔福代码:

program libiup_integration;
{$APPTYPE CONSOLE}

uses
  SysUtils,
  WinProcs;

type
  T_F_GetError = function() : pchar; stdcall;

  T_F_SetPath = function(path: pchar) : integer; stdcall;

  T_F_GetStrat = function(date: integer;time: single;lat:  single;lon:  single) : single; cdecl;

var
  F_GetError  : T_F_GetError;
  PF_GetError : TFarProc;
  F_SetPath   : T_F_SetPath;
  PF_SetPath  : TFarProc;
  F_GetStrat  : T_F_GetStrat;
  PF_GetStrat : TFarProc;
  DLLHandle   : THandle;
  errormsg  : pchar;
  h5path    : pchar;
  h5err     : integer;
  date      : integer;
  time      : single;
  lat       : single;
  lon       : single;
  strat     : single;
  i         : integer;

begin
  DLLHandle := LoadLibrary('libiup.dll');
  if DLLHandle <> 0 then
    begin
      { construct the function pointers }
      PF_GetError := GetProcAddress(DLLHandle, 'getError');
      PF_SetPath := GetProcAddress(DLLHandle, 'setPath');
      PF_GetStrat := GetProcAddress(DLLHandle, 'getStrat');

      { If the function pointer is valid ... }
      if (PF_GetError <> nil) and (PF_SetPath <> nil) and (PF_GetStrat <> nil) then
        begin
          { Assign the function pointer to the function handle }
          @F_GetError := PF_GetError;
          @F_SetPath := PF_SetPath;
          @F_GetStrat := PF_GetStrat;

          errormsg := StrAlloc(4096);

          h5path := StrAlloc(256);
          StrCopy(h5path, 'z:data\%Y%m.h5');
          h5err := F_SetPath(h5path);
          if h5err < 0 then
            begin
              errormsg := F_GetError();
              WriteLn(errormsg);
            end;

          for i := 1 to 10 do
            begin
              date := 4745;
              time := 12.34 + i/10;
              lat  := -35.321 + i*i;
              lon  := 115.67 - i*i;

              strat := F_GetStrat(date, time, lat, lon);
              if strat < 0. then
                begin
                  errormsg := F_GetError();
                  WriteLn(errormsg);
                end;

               WriteLn('Value returned by getStrat call no. ' + IntToStr(i) + ': ' + FloatToStr(strat));
             end;

          { and finally, delete the function pointers ...}
          PF_SetPath := nil;
          PF_GetStrat := nil;
          PF_GetError := nil;
          FreeLibrary(DLLHandle);
          WriteLn('Press ENTER to continue ...');
          ReadLn;
        end

      else
      { The function pointer was not valid, so this means that the function was not found in the dll. }
        begin
          WriteLn('Function not found');
          RaiseLastOSError;
        end;
    end

  else
  { The LoadLibrary function did not return a valid DLL handle. }
    begin
      WriteLn('DLL not loaded');
      FreeLibrary(DLLHandle);
      WriteLn('Press ENTER to continue ...');
      ReadLn;
    end;
end.

dll.h

#ifndef LIBIUP_DLL_H_
#define LIBIUP_DLL_H_
#ifdef BUILD_DLL
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif

#include "stratcalc/SimpleStratosphericColumnCalculator.h"
#include <iostream>
#include <string>
#include "boost/date_time/posix_time/posix_time.hpp"

#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif
    WIN32DLL_API BOOL __stdcall DllMain( HANDLE, DWORD, LPVOID);
    WIN32DLL_API  int setPath(char*);
    WIN32DLL_API  const char* getError();
    WIN32DLL_API float getStrat(int, float, float, float);
    std::string errormsg;
    SimpleStratosphericColumnCalculator* calc; 
#ifdef __cplusplus
}                       /* End of extern "C" */
#endif

#endif

dll.cpp

#ifdef BUILD_DLL
#include "windows.h"
#include "dll.h"
#include <iostream>
// different functions of this library
= new SimpleStratosphericColumnCalculator();


WIN32DLL_API BOOL __stdcall DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            calc = new SimpleStratosphericColumnCalculator();
            break;
        case DLL_THREAD_ATTACH:
            calc = new SimpleStratosphericColumnCalculator();
            break;
        case DLL_THREAD_DETACH:
            delete calc;
            break;
        case DLL_PROCESS_DETACH:
            delete calc;
            break;
    }

    return TRUE;
}


WIN32DLL_API int setPath(char* Path)
{
    errormsg = "";
    return calc->setPath(Path);
}

WIN32DLL_API const char* getError()
{
    std::cout << errormsg << std::endl;
    return errormsg.c_str();
}

WIN32DLL_API float getStrat(int Date, float Time, float Lat, float Lon)
{
    errormsg = "";
    if (Lat < -90. || Lat > 90.)
        errormsg += "Latitude value out of bounds.
";
    if (Lon < 0. || Lon > 360.)
        errormsg += "Longitude value out of bounds.
";
    if (errormsg != "")
        return -1.;
    return (float)calc->getStrat(Date, Time, Lat, Lon);
}
#else
#endif

推荐答案

检查调用约定.我在 2 个函数中看到 stdcall,在一个函数中看到 cdecl.尝试将所有内容更改为 stdcall 或 cdecl 并查看是否有效

Check the calling conventions. I see stdcall in 2 functions and cdecl in one function. Try to change everything to stdcall or cdecl and see if it works

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆