现在的位置: 首页 > 综合 > 正文

.NET调用非托管程式(标准DLL篇)

2013年02月18日 ⁄ 综合 ⁄ 共 4264字 ⁄ 字号 评论关闭

前端时间写了篇.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.

在Delphi中如下调用,可以通过

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;

但是在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);
            }

        }

源代码:http://files.cnblogs.com/arping/testCOM.rar

抱歉!评论已关闭.