前端时间写了篇.Net调用Delphi写的COM接口,同一套算法在不同的环境下运行,但后来想了想写成COM,别的程序调用COM效率太低,如果写成标准的DLL也许高些,于是尝试把压缩加密算法写成标准的DLL.
1.在Delphi6中新建一个Dll 扩展,把加密压缩单元引用进来,申明函数
library CompressDll;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
DES in 'DES.pas',
uSoapPacketComUnCompressor in 'uSoapPacketComUnCompressor.pas';
procedure CompressData(const sSource : string;out sTarget : string) export; stdcall;
begin
sTarget := XTToCompressSoapPacket(sSource);
end;
procedure unCompressData(const sSource : string;out sTarget : string) export; stdcall;
begin
sTarget := XTToUnCompressSoapPacket(sSource);
end;
procedure DeCryptData(const sSource, aKey: string;out sTarget : string) export; stdcall;
begin
sTarget := DeCrypt(sSource,aKey);
end;
procedure EnCryptData(const sSource, aKey: string;out sTarget : string) export; stdcall;
begin
sTarget := EnCrypt(sSource,aKey);
end;
procedure ShowMe(const aStr :array of Byte ;out aData : array of Byte) export ;stdcall;
var
SysLogFilePath : string;
NewLogFile: TFileStream;
SysEventLogFile : TextFile;
i : integer;
a : Byte;
begin
SysLogFilePath := 'D:\1.log';
if not FileExists(SysLogFilePath) then
begin
NewLogFile := TFileStream.Create(SysLogFilePath, fmCreate or fmShareDenyRead);
if Assigned(NewLogFile) then
FreeAndNil(NewLogFile);
end;
AssignFile(SysEventLogFile, SysLogFilePath);
try
try
Append(SysEventLogFile);
Writeln(SysEventLogFile,
DateTimeToStr(Now) + aStr);
a := 'd';
aData = aStr + a;
finally
CloseFile(SysEventLogFile);
end;
except
on e : exception do
begin
//抛弃异常
end;
end;
end;
{$R *.res}
exports
CompressData,unCompressData,DeCryptData, EnCryptData,ShowMe;
begin
end.
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
DES in 'DES.pas',
uSoapPacketComUnCompressor in 'uSoapPacketComUnCompressor.pas';
procedure CompressData(const sSource : string;out sTarget : string) export; stdcall;
begin
sTarget := XTToCompressSoapPacket(sSource);
end;
procedure unCompressData(const sSource : string;out sTarget : string) export; stdcall;
begin
sTarget := XTToUnCompressSoapPacket(sSource);
end;
procedure DeCryptData(const sSource, aKey: string;out sTarget : string) export; stdcall;
begin
sTarget := DeCrypt(sSource,aKey);
end;
procedure EnCryptData(const sSource, aKey: string;out sTarget : string) export; stdcall;
begin
sTarget := EnCrypt(sSource,aKey);
end;
procedure ShowMe(const aStr :array of Byte ;out aData : array of Byte) export ;stdcall;
var
SysLogFilePath : string;
NewLogFile: TFileStream;
SysEventLogFile : TextFile;
i : integer;
a : Byte;
begin
SysLogFilePath := 'D:\1.log';
if not FileExists(SysLogFilePath) then
begin
NewLogFile := TFileStream.Create(SysLogFilePath, fmCreate or fmShareDenyRead);
if Assigned(NewLogFile) then
FreeAndNil(NewLogFile);
end;
AssignFile(SysEventLogFile, SysLogFilePath);
try
try
Append(SysEventLogFile);
Writeln(SysEventLogFile,
DateTimeToStr(Now) + aStr);
a := 'd';
aData = aStr + a;
finally
CloseFile(SysEventLogFile);
end;
except
on e : exception do
begin
//抛弃异常
end;
end;
end;
{$R *.res}
exports
CompressData,unCompressData,DeCryptData, EnCryptData,ShowMe;
begin
end.
procedure TForm1.BitBtn1Click(Sender: TObject);
var
sSource : string;
sTarget : string;
LibHandle: THandle;
CompressData : TCompressData;
begin
sSource := self.Edit1.Text ;
if( sSource = '') then
begin
exit;
end;
LibHandle := LoadLibrary(PChar(UPDATE_DATA_DLL_PATH));
try
if LibHandle = HINSTANCE_ERROR then
raise EDLLLoadError.Create('Unable to Load DLL');
@CompressData := GetProcAddress(LibHandle, 'CompressData');
if not (@CompressData = nil) then
begin
sTarget := CompressData(sSource);
self.Edit2.Text := sTarget;
end;
finally
{unload the DLL}
FreeLibrary(LibHandle);
end;
end;
var
sSource : string;
sTarget : string;
LibHandle: THandle;
CompressData : TCompressData;
begin
sSource := self.Edit1.Text ;
if( sSource = '') then
begin
exit;
end;
LibHandle := LoadLibrary(PChar(UPDATE_DATA_DLL_PATH));
try
if LibHandle = HINSTANCE_ERROR then
raise EDLLLoadError.Create('Unable to Load DLL');
@CompressData := GetProcAddress(LibHandle, 'CompressData');
if not (@CompressData = nil) then
begin
sTarget := CompressData(sSource);
self.Edit2.Text := sTarget;
end;
finally
{unload the DLL}
FreeLibrary(LibHandle);
end;
end;
但是在C#中如下调用,通过查看日志,却把字符串截断了一部分,如果标准DLL返回的不是string类型而是Integer或者是procedure都可以调用成功。希望有高手能指点一二。
[DllImport("CompressDll.dll",CharSet=CharSet.Unicode,SetLastError=true)]
public static extern void CompressData(string sSource,ref string sTarget);
[DllImport("CompressDll.dll",CharSet=CharSet.Unicode,SetLastError=true)]
public static extern void unCompressData(string sSource,ref string sTarget);
[DllImport("CompressDll.dll",CharSet=CharSet.Ansi,SetLastError=true)]
public static extern void ShowMe(string aStr,ref string aData);
private void button5_Click(object sender, System.EventArgs e)
{
if(this.textBox1.Text == string.Empty)
{
MessageBox.Show("null param");
}
try
{
string aSource = this.textBox1.Text;
string aTarget = string.Empty;
ShowMe(aSource,ref aTarget);
//CompressData(aSource,ref aTarget);
this.textBox2.Text = aTarget;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public static extern void CompressData(string sSource,ref string sTarget);
[DllImport("CompressDll.dll",CharSet=CharSet.Unicode,SetLastError=true)]
public static extern void unCompressData(string sSource,ref string sTarget);
[DllImport("CompressDll.dll",CharSet=CharSet.Ansi,SetLastError=true)]
public static extern void ShowMe(string aStr,ref string aData);
private void button5_Click(object sender, System.EventArgs e)
{
if(this.textBox1.Text == string.Empty)
{
MessageBox.Show("null param");
}
try
{
string aSource = this.textBox1.Text;
string aTarget = string.Empty;
ShowMe(aSource,ref aTarget);
//CompressData(aSource,ref aTarget);
this.textBox2.Text = aTarget;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}