Due to project needs, I used Delphi to write a dll that connects the database to export the data to the Sql file, which uses the TADOQuery component.
There is only one export method:
function DataExport(path,ini_path:PChar):integer;
After writing, I wrote a test.exe with delphi for testing and found that it could be used normally.
Then he handed the dll to his colleague and asked him to call it in PowerBuilder. After taking it, my colleague found that once DataExportPB is called, it is reported that the target Dll cannot be opened. I think it might be because the environments running on both sides are different, so I copied the test.exe and tried it. Strangely, test.exe runs fine.
In order to determine where the problem really occurs, I used Python and C# to test it again. There was no problem below C#, but Python reported an error:
CoInitialize() is not called
After reviewing the information, I found that if the ADO component is used in the Dll of Delphi, then the CoInitialize method of ActiveX needs to be called before use. After knowing the problem, it becomes much easier. Before creating TADOQuery in the source code, CoInitialize() is called, and the Python call is successful.
I thought PowerBuilder should be fine, but who knew it would be the same problem. I can't figure it out now. The ctypes module in Python uses the call method in C and the parameter passing method should be the same as PowerBuilder, but why is it still not possible in PB? My colleague asked me to write an extra output method in Dll to try it out. OK, I wrote another method like this:
function test:PChar;
Begin
result := 'Test string from test';
end;
The test method was called successfully in PB, and then the colleague tried to call DataExport again, and it was successful! ! ? ? Why? This test method just outputs a fixed string. Why is DataExport called successfully? I'm really puzzled.
But another problem occurred at this time. Once the PB application is exited, a memory operation error occurred.
I carefully checked the Delphi code and found out using the figure whether it was not released. My code is as follows:
function DataExport(path,ini_path:PChar):integer;
var
query : TADOQuery;
Begin
.........
CoInitialize();
query := TADOQuery.Create(nil);
.........
query.Close;
query.Free;
CoUnInitialize();
.........
end;
Nothing wrong! In desperation, I divided CoInitialize() and CoUnInitialize() into two independent methods.
function init:integer;
Begin
try
CoInitialize();
result := 1;
except
on Exception:
result := 0;
end;
end;
function uninit:integer;
Begin
try
CoUnInitialize();
result := 1;
except
on Exception:
result := 0;
end;
end;
Then let the colleague call init first in the form initialization event, and then close the event to call uninit. Problem solved. Everything is normal.
Although the problem has been solved, I still don't understand why I do this.