调用com组件出现很奇怪的报错,详细请进来看。 (300分)

  • 主题发起人 主题发起人 叶不归
  • 开始时间 开始时间

叶不归

Unregistered / Unconfirmed
GUEST, unregistred user!
先说说那个com组件,接口我声明如下(一部分):<br>&nbsp; TBBuf = record<br>&nbsp; &nbsp; dwSize: DWORD;<br>&nbsp; &nbsp; pvBuffer: DWORD;<br>&nbsp; end;<br><br>&nbsp; TPn = record<br>&nbsp; &nbsp; HNo: Byte;<br>&nbsp; &nbsp; Hdl: DWORD;<br>&nbsp; end;<br><br>&nbsp; IApiMgr = interface(IUnknown)<br>&nbsp; &nbsp; ['{25E4A41D-59D1-4274-AE4A-30F39DAECA3E}']<br>&nbsp; &nbsp; function InitB(BnP: BAD; dwExt: DWORD; Pn: DWORD): HResult; safecall;<br>&nbsp; &nbsp; function UninitB(Pn: DWORD): HResult; safecall;<br>&nbsp; end;<br><br>其中<br>type BAD = (BAD_D, BAD_L, BAD_U);<br><br>public<br>&nbsp; &nbsp; BBuf: TBBuf;<br>&nbsp; &nbsp; Pn: TPn;<br>&nbsp; &nbsp; ApiMgr: IApiMgr;<br>&nbsp; &nbsp; procedure a;<br>&nbsp; &nbsp; procedure b;<br>end;<br><br>procedure TForm1.a;<br>begin<br>&nbsp; ApiMgr.CreateComObj(CLSID) as IApiMgr; //成功<br>&nbsp; BBuf.dwSize := sizeof(TPn);<br>&nbsp; BBuf.pvBuffer := LongInt(@Pn);<br>&nbsp; ApiMgr.InitB(BAD_L, 0, LongInt(@BBF)); //成功<br>&nbsp; (位置1)<br>end;<br><br>procedure TForm1.b;<br>begin<br>&nbsp; (位置2)<br>&nbsp; ApiMgr.UninitB(LongInt(@Pn)); //语句1 //调用时内存报错。<br>end;<br><br>怪事出现了:<br>&nbsp; 做法1. 把语句1放在位置1时,正常。<br>&nbsp; 做法2. 在位置2前加上这么一句memo1.lines.add('a:' + IntToStr(Application.Handle));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;就正常了。而且还一定要有(Application.Handle)这么一段,单单<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;memo1.lines.add('a:');也仍旧出错。<br><br>请问,这是为什么??<br><br>我可能表达的不是很清楚,有疑问请提出。<br>
 
可能长了点,请耐心看一下,结构并不复杂。<br>有人吗?
 
没人遇到这种情况吗?<br>能不能说说调用com需要注意点什么?
 
我从来都是用C或C++写com的,很少见到用object pascal的。<br>不过从程序看是内存出错的现象以及基本概念不清楚。<br>还有可以看出你想处理Tpn对象,想通过地址传送,但是<br>1、类型不符<br>function InitB(BnP: BAD; dwExt: DWORD; Pn: DWORD): HResult; safecall<br>ApiMgr.InitB(BAD_L, 0, LongInt(@BBF)); <br>地址是32位无符号数,你的接口定义正确,但LongInt是带符号的32整数。<br>2、@BBF本来是取地址操作,返回的就是32位无符号数。<br>3、可否考虑用ATL进行COM开发。<br><br>
 
谢谢yyii的回答,我没说清,这个com是我要调用的,不是delphi开发的。<br>1.2. 类型:我换成Dword(@BBF)也是同样的报错, 我想地址一般是不会超过31位整数的,<br>有无符号并没太大关系。<br>3.我只是com调用,未涉及开发。<br>还有办法吗?
 
可否这样:<br>ApiMgr.InitB(BAD_L, 0, @BBF); <br>ApiMgr.UninitB(@Pn); <br>
 
yyii,那得把接口类型DWORD改为 Pointer才行,<br>你认为是接口类型声明错了吗?<br>原来是这样的:<br>typedef struct {<br> DWORD dwSize; //Size of the following structure in bytes<br> PVOID pvBuffer;<br>} BBuf, *BBufPtr;<br><br>typedef struct {<br> BYTE HNo;<br> DWORD Hdl;<br>} Pn, *PnPtr;<br><br>virtual HRESULT __stdcall InitB(BAD Bd, DWORD dwExt, DWORD Pn) = 0;<br>virtual HRESULT __stdcall UninitB(DWORD Pn) = 0;<br><br>我想我那样声明应该是对的。<br>
 
这样:<br>function InitB(BnP: Integer; dwExt: DWORD; Pn: pointer): HResult;<br><br>var<br>aaa :^TPn;<br>begin<br>aaa^.HNo := 0;<br>aaa^.Hdl := 0;<br>InitB(0,0,aaa);<br>end;
 
yyii,这样写有什么不一样吗?:(
 
function InitB(BnP: Integer; dwExt: DWORD; Pn: pointer): HResult;<br>没看见参数改了吗?
 
首先我觉得头文件的转换不太合适,我印象中VC中的结构对应到Delphi都是Packed record<br>具体使用中对于指针的传送,因为应用程序的地址在2G以下,所以31、32位是一样的,<br>但即使在2G以上,用LongInt也没关系,在寄存器中,传递的都是同样的值,不过<br>一般还是写成DWORD<br>另外Delphi是强类型检查的,是指针的地方,根据具体情况还是声明称<br>Var 参数或指针比较好<br><br>说道搂主的具体情况,我看不出有什么问题,我想你还是跟踪以下汇编代码比较好<br>,注意在之间,插上几句不相关的,把已经在寄存器中的值冲掉,看起来更清楚<br>,我觉得可能是Packed的问题,好像又不是,说不好。<br><br>
 
其实结构肯定是要对齐的c和pascal我想处理的方式是一样的。<br>因为Delphi是强类型检查的,所以用pointer类型比较好。
 
咳,算了,用C了。
 
多人接受答案了。
 
后退
顶部