关于DELPHI下的指针. ( 积分: 100 )

  • 主题发起人 主题发起人 rollin7
  • 开始时间 开始时间
R

rollin7

Unregistered / Unconfirmed
GUEST, unregistred user!
一直用的是C,对PASCAL并不是很熟,现在一个项目遇到了如下问题.
调用VC写的动态链接库,函数原型如下:
typedef int (*PicRecog)(char *output, int output_len, BYTE* pInput, DWORD Len, BYTE* pExtractImg, int* nPaintLocation, int* isYellow, int* isGreen, int* isRotation);

其中,nPaintLocation为一整型数组,而isYellow,isGreen,isRotation是一整型数.

请问在DELPHI中该如何声明这个函数和定义里面的参数.
我是如下做的,大家看看有没有什么问题,请指教一二.

type PicRecog= function (output:PChar
Len1:DWORD
pOriBmp:PByte
len2:DWORD
pExtractImg:PByte
nPaintLocation:PInteger
var isYellow:integer
var isGreen:integer
var isRotation:integer):integer;

在实际应用时是如下定义与调用
MyPicRecog: PicRecog;

DLLHandle : HModule;

output:PChar;

pOriBmp,pExtractImg:PByte;

nPaintLocation:PInteger;

actual_chars :integer;
isYellow :integer;
isGreen :integer;
isRotation :integer;
len:int64;

////用GetMem对output,pOriBmp,pExtractImg,nPaintLocation分配内存

DLLHandle := LoadLibrary('*.dll');

MyPicRecog:= GetProcAddress(DLLHandle , '*Func');

//*.dll是一动态链接库, *Func是要调用的函数,单步调试,函数装载成功

actual_chars:=MyPicRecog(output, 512, pOriBmp, Len, pExtractImg, nPaintLocation, isYellow, isGreen, isRotation);

可是一调用就出错,晕死,请问各位老大到底哪儿出了错,函数声明应该怎么声明,具体应用时应该怎么定义参数和传递参数,不甚感激
 
type PicRecog= function (output:PChar
Len1:DWORD
pOriBmp:PByte
len2:DWORD
pExtractImg:PByte
nPaintLocation:PInteger
var isYellow:integer
var isGreen:integer
var isRotation:integer):integer
cdecl;
 
MyPicRecog:= GetProcAddress(DLLHandle , '*Func')
该行改为:
@MyPicRecog:= GetProcAddress(DLLHandle , '*Func');
 
MyPicRecog:= GetProcAddress(DLLHandle , '*Func')
该行改为:
@MyPicRecog:= GetProcAddress(DLLHandle , '*Func')

已改过,在声明后面加了cdecl之后还是不行,郁闷.
 
我写了个小例子
//c++的 mydll.dll
extern "C"_declspec(dllexport) int add(int a,int b)
{
return a+b;
}

extern "C"_declspec(dllexport)int subtract(int a,int b)
{
return a-b;
}

//delphi 的调用

unit Unit1;

interface

uses
ShareMem ,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
type
TIntFunc=function(i:integer;j:integer):integer;stdcall;
var
Th:Thandle

Tf:TIntFunc;
Tp:TFarProc;
a ,b: integer;
s : string;
begin
a:=2;
b:=3;
Th:=LoadLibrary('mydll.dll')
{装载DLL}
if Th>0 then
try
Tp:=GetProcAddress(Th,PChar('add'));
if Tp<>nil
then
begin
Tf:=TIntFunc(Tp);
s:=IntToStr(Tf(a,b))
{调用TestC函数}
end
else
ShowMessage('TestC函数没有找到');
finally
FreeLibrary(Th)
{释放DLL}
end
else
ShowMessage('ddd.dll没有找到');
Edit1.Text := s;
end;

end.
 
根据调试,个人觉得还是函数参数传递的时候出现了错误,因为函数已进去了,正确调用,但是在里面处理时出了错,具体错误为:Invalid floating point operation.郁闷,到底是哪儿出了错呢/
 
我觉得也是参数传递的问题,但现在没发现问题所在。
一般DLL引出的都是采用stdcall,可是从你的声明看不出来,你不妨把cdecl换成stdcall
看看。
 
现在已经改了,函数声明改为:type TPicRecog= function (output:PChar
Len1:DWORD
pOriBmp:PByte
len2:DWORD
pExtractImg:PByte
nPaintLocation:PInteger
var isYellow:integer
var isGreen:integer
var isRotation:integer):integer;stdcall;

MyPicRecog: TPicRecog;
DllHandle : HMODULE;

DllHandle := LoadLibrary('recog.dll');

if DllHandle<>0 then
@MyPicRecog:= GetProcAddress(DllHandle, 'recog_func');

if not (@MyPicRecog=nil) then
MyPicRecog(output, 512, pOriBmp, Len, pExtractImg, nPaintLocation, isYellow, isGreen, isRotation);

用单步调试,已进入函数了,但报错:Invalid floating point operation.

如果在VC下调用此动态链接库则没任何问题,郁闷了.
 
各种方法都试过了,还是出现同样的错误提示,郁闷,没招了.望哪位大侠指教一二.
 
自己来顶一下,问题还没解决.
 
整形数组,用 PintegerArray 类型看看。
 
function (output:PChar
Len1:DWORD
pOriBmp:PByte
len2:DWORD
pExtractImg:PByte
nPaintLocation:PInteger
var isYellow:integer
var isGreen:integer
var isRotation:integer

output: PChar ==> 明显需要调用者提供空间,不只是一个指针
pOriBMP, pExtractImg如上
 
楼上的可能没看清,我注释了的,用GetMem对output,pOriBmp,pExtractImg,nPaintLocation分配内存

GetMem(output, sizeof(Char) * 512);
GetMem(pOriBmp, sizeof(Byte) * FileSize);
GetMem(pExtractImg, sizeof(Byte) * FileSize);
GetMem(nPaintLocation, sizeof(integer) * 4);

FileSize是我所打开的位图文件大小.

另:我改用PIntegerArray之后出现一样的错误.看来不是此问题.

同时,把VC下的函数原型改为DELPHI下的声明,不知道有没有改错.
 
你把VC的调用发上来看看,或者tseug@263.net
 
OK,VC调用如下:
typedef int (*LPRMain)(char *output, int output_len, BYTE* pInput, DWORD Len, BYTE* pExtractImg, int* nPaintLocation, int* isYellow, int* isGreen, int* isRotation);

CString FileName=&quot;F://Delphi//测试图片//j000422.bmp&quot;;

CFile oriFile;

BOOL FileOpen=oriFile.Open(FileName, CFile::modeRead);

if(FileOpen == FALSE)
{
MessageBox(&quot;打开文件错误,请重新打开!&quot;,MB_OK);
return;
}

DWORD Leng=oriFile.GetLength();

BYTE* pOriBmp = new BYTE [Leng];

DWORD nBytesRead =oriFile.Read(pOriBmp, Leng);

oriFile.Close();

char output[512];

int actual_chars;

BYTE* pExtractImg = new BYTE[Leng];

int nPaintLocation[4];

int isYellow;

int isGreen;

int isRotation;

output[0]='/0';

LPRMain m_LPRMain = NULL;
HMODULE m_lprHandle = NULL;

m_lprHandle = LoadLibrary(&quot;lprdll.dll&quot;);
if ( m_lprHandle!=NULL )
m_LPRMain = (LPRMain)::GetProcAddress(m_lprHandle, &quot;LPRMain_Func&quot;);

actual_chars = (*m_LPRMain)(output, 512, pOriBmp, Leng, pExtractImg, nPaintLocation, &amp;isYellow, &amp;isGreen, &amp;isRotation);

MessageBox(output);

delete pExtractImg;

delete pOriBmp;
 
完整的Delphi调用如下:

type TPicAdjust = function (output:PChar
Len1:Integer
pOriBmp:PByte
len2:DWORD
pExtractImg:PByte
nPaintLocation:PInteger
var isYellow:Integer
var isGreen:Integer
var isRotation:Integer) : Integer;stdcall;

procedure TForm1.Button1Click(Sender: TObject);
var
output:PChar;
pOriBmp,pExtractImg:PByte;

nPaintLocation:PInteger;

isYellow :Integer;
isGreen :Integer;
isRotation :Integer;

actual_chars :integer;

len:DWORD;

MyFile:TFileStream;
FileSize:DWORD;

MyPicAdjust: TPicAdjust;
DllHandle : HMODULE;
begin
OpenDialog1.Execute;

if OpenDialog1.FileName='' then
exit;

Image1.Picture.LoadFromFile(OpenDialog1.FileName);

MyFile:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
FileSize:=MyFile.Size;

ShowMessage(IntToStr(sizeof(Byte)));

GetMem(output, sizeof(Char) * 512);
GetMem(pOriBmp, sizeof(Byte) * FileSize);
GetMem(pExtractImg, sizeof(Byte) * FileSize);
GetMem(nPaintLocation, sizeof(integer) * 4);

len:=MyFile.Read(pOriBmp^,FileSize);

DllHandle := LoadLibrary('lprdll.dll');

if DllHandle<>0 then
@MyPicAdjust := GetProcAddress(DllHandle, 'LPRMain_Func');

if not (@MyPicAdjust=nil) then
MyPicAdjust(output, 512, pOriBmp, Len, pExtractImg, nPaintLocation, isYellow, isGreen, isRotation);

FreeLibrary(DllHandle);

freemem(output);
freemem(pOriBmp);
freemem(pExtractImg);
freemem(nPaintLocation);
end;
 
代码中没发现有什么不对的,你把DLL发我邮箱里我试试吧
 
typedef int (*PicRecog)(char *output,
int output_len,
BYTE* pInput,
DWORD Len,
BYTE* pExtractImg,
int* nPaintLocation,
int* isYellow,
int* isGreen,
int* isRotation);
注意C的默认调用约定是Cdecl,除非你加__stdcall修饰符.否则Delphi中声明就要是Cdecl约定方式


Type
PicRecog = Function (output:Pchar;
output_len : Integer;
pInput : PByte;
Len : DWORD;
pExtractImg: PByte;
nPaintLocation: PInteger;
isYellow : PInteger;
isGreen : PInteger;
isRotation : PInteger):Integer;cdecl
//注意Cdcel约定方式

调用的时候
actual_chars:=MyPicRecog(output,
512,
pOriBmp,
Len,
pExtractImg,
nPaintLocation,
@isYellow,
@isGreen,
@isRotation);
 
楼上的,改了之后还是不行,出现一样的错误提示,Invalid floating point operation.

对于tseug,实在抱歉,此动态链接库涉及核心技术,不方便发给你.
 
建议你在VC下对DLL进行跟踪调试,看看参数是否传递正确
 
后退
顶部