4

私は、Delphi で DLL を作成することに初めて取り組みました。ここまでは順調ですね。typelib を使用することで、Widestrings を DLL との間で問題なく受け渡すことができました。

現時点で興味深いのは、VB6 をテストベッドとして使用していて、IDE 内でテストを実行するたびに、プログラムが実行され、IDE プロセスが突然メモリから消えてしまうことです。エラー メッセージも何も表示されません。コードをステップ実行すると、最後の行を実行するまですべてが正常に機能し、その後 IDE が消えます。

対照的に、テストを EXE にコンパイルすると、プログラムは最後まで実行され、エラー メッセージなどは表示されません。

誰かが以前にこの問題を抱えていましたか?私を見つめている明らかな解決策はありますか?

重要な場合に備えて、以下のソースコード:

- 事業

library BOSLAD;

uses
  ShareMem,
  SysUtils,
  Classes,
  BOSLADCode in 'BOSLADCode.pas';

exports
  version,
  DMesg,
  foo;
{$R *.res}

begin
end.

- 単位

unit BOSLADCode;

interface
  function version() : Double; stdcall;
  procedure DMesg(sText : WideString; sHead : WideString ); stdcall;
  function foo() : PWideString; stdcall;

implementation
  uses Windows;

  function version() : Double;
  var
    s : String;
  begin
    result := 0.001;
  end;

  procedure DMesg( sText : WideString; sHead : WideString);
  begin
    Windows.MessageBoxW(0, PWideChar(sText), PWideChar(sHead), 0);
  end;

  function foo() : PWideString;
  var s : WideString;
  begin
    s := 'My dog''s got fleas';
    result := PWideString(s);
  end;
end.

-- タイプライブラリ

 // This is the type library for BOSLAD.dll
      [
      // Use GUIDGEN.EXE to create the UUID that uniquely identifies
      // this library on the user's system. NOTE: This must be done!!
         uuid(0C55D7DA-0840-40c0-B77C-DC72BE9D109E),
      // This helpstring defines how the library will appear in the
      // References dialog of VB.
         helpstring("BOSLAD TypeLib"),
      // Assume standard English locale.
         lcid(0x0409),
      // Assign a version number to keep track of changes.
         version(1.0)
      ]
      library BOSLAD
      {

      // Now define the module that will "declare" your C functions.
      [
         helpstring("Functions in BOSLAD.DLL"),
         version(1.0),
      // Give the name of your DLL here.
         dllname("BOSLAD.dll")
      ]
      module BOSLADFunctions
      {
[helpstring("version"), entry("version")] void __stdcall version( [out,retval] double* res );
[helpstring("DMesg"), entry("DMesg")] void __stdcall DMesg( [in] BSTR msg, [in] BSTR head );
[helpstring("foo"), entry("foo")] void __stdcall foo( [out,retval] BSTR* msg );
      } // End of Module
      }; // End of Library

WideString の宣言を、それを宣言した関数の外側に移動しました。これにより、変数の有効期間が関数の有効期間よりも長くなることが期待されfooます。それは何の違いもありませんでした。

foo同様に、関数の呼び出しを VB6 からコメントアウトしました。それも違いはありませんでした。何をしても、コードの最後の行が実行された後に VB6 IDE が停止します。

ローカル変数へのポインタ以外に原因があります。しかし、何?

4

5 に答える 5

2
result := PWideString(s);

ここでは、ローカル変数へのポインタを返しています。すぐに無効になります。

于 2008-10-11T06:59:03.253 に答える
1

GSergの答えを詳しく説明するには:

result := PWideString(s);

s は文字列リテラルで初期化されたので大丈夫だと思うでしょう...しかし、Delphi のワイド文字列は通常の文字列のように参照カウントされないため、s は実際には動的に割り当てられたヒープ メモリを少し保持し、関数がこのメモリを再利用できることを返します:(

ただし、次の場合は問題ありません。

function foo() : PWideString;
const s : WideString = 'My dog''s got fleas';
begin
  result := PWideString(s);
end;
于 2008-10-11T11:18:54.527 に答える
1

delphi.wikia.com サイトでDLLを作成すると、私が探していた答えが見つかります。そして解決策も。

たとえば、Delphi は文字列を格納するためのメモリを自動的に割り当てて解放し、不要になったときなどを認識します。同じことが Visual Basic などにも当てはまりますが、どちらも異なる方法で行います。そのため、Visual Basic によって割り当てられた文字列を Delphi で記述された DLL に渡すと、大きな問題が発生します。これは、両方が文字列を管理しようとして、お互いの髪の毛に侵入するためです。

解決策はFastMMを使用することであり、見事に機能します!! BORLNDMM.DLL私は今、自分のプロジェクトに置き換えており、すべてがうまくいきます。

于 2008-10-11T15:07:11.913 に答える
0

これを閉じることができると思います。以下のコードは、人々を満足させるのに十分であるように思わnews:comp.lang.pascal.delphi.miscれ、概念のテストから実際にそれを使って何かをすることに本当に移る必要があります.

BOSLAD.bdsproj:

library BOSLAD;

uses
  BOSLADCode in 'BOSLADCode.pas';

exports
  version,
  DMesg,
  foo;
{$R *.res}

begin
end.

BOSLADCode.pas:

unit BOSLADCode;

interface
  function version() : Double; stdcall;
  procedure DMesg(const sText : WideString; const sHead : WideString ); stdcall;
  function foo() : PWideChar; stdcall;

implementation
  uses Windows, ActiveX;


  function version() : Double;
  begin
    result := 0.001;
  end;

  procedure DMesg( const sText : WideString; const sHead : WideString);
  begin
    Windows.MessageBoxW(0, PWideChar(sText), PWideChar(sHead), 0);
  end;

  function foo() : PWideChar;
  var s : WideString;
  begin
    s := 'My dog''s got fleas';
    result := SysAllocString(PWideChar(s));
  end;
end.

これで VB は快適になり、おかしな IDE のクラッシュは発生しなくなりました。

于 2008-10-17T15:54:15.417 に答える
0

これについては、Rob Kennedy のニュース:comp.lang.pascal.delphi.misc に感謝します。

彼は、とりわけ次のように述べています。

  1. この DLL は、ShareMem、SysUtils、またはクラスを必要としません。
  2. WideString を取得し、それが実際には WideString へのポインターであることをコンパイラーに伝えました。あなたはコンパイラに嘘をついています。気にしませんが、この関数の呼び出し元はおそらく気にします。

したがって、ShareMem (および DLL ウィザードによって追加された SysUtils と Classes) がなくても問題なく動作する改訂されたコードは次のとおりです。

library BOSLAD;
uses
  BOSLADCode in 'BOSLADCode.pas';
exports
  version,
  DMesg,
  foo;
{$R *.res}
begin
end.

BOSLADCode.pas:

unit BOSLADCode;

interface
  function version() : Double; stdcall;
  procedure DMesg(sText : PWideChar; sHead : PWideChar ); stdcall;
  function foo() : PWideChar; stdcall;

implementation
  uses Windows;

  var s : WideString;

  function version() : Double;
  begin
    result := 0.001;
  end;

  procedure DMesg( sText : PWideChar; sHead : PWideChar);
  begin
    Windows.MessageBoxW(0, sText, sHead, 0);
  end;

  function foo() : PWideChar;
  begin
    s := 'My dog''s got fleas';
    result := PWideChar(s);
  end;
end.

boslad.odl:

// This is the type library for BOSLAD.dll
[
uuid(0C55D7DA-0840-40c0-B77C-DC72BE9D109E),
helpstring("BOSLAD TypeLib"),
lcid(0x0409),
version(1.0)
]
library BOSLAD
{
[
helpstring("Functions in BOSLAD.DLL"),
version(1.0),
dllname("BOSLAD.dll")
]
module BOSLADFunctions
{
[helpstring("version"), entry("version")] 
    void __stdcall version( [out,retval] double* res );
[helpstring("DMesg"), entry("DMesg")] 
    void __stdcall DMesg( [in] BSTR msg, [in] BSTR head );
[helpstring("foo"), entry("foo")] 
    void __stdcall foo( [out,retval] BSTR* msg );
} 
}; 

test.bas:

Sub Main()
    Dim cfg As New CFGProject.cfg
    cfg.Load "test.cfg"
    Dim s As String
    s = cfg.Recall("msg")
    DMesg s, "" & version
    s = foo
    DMesg s, "" & version
End Sub

test.cfg

msg=毅訜訝

そのすべてが完璧に機能します。VB6 の IDE は問題なく DLL を実行し、MsgBox はすべて正常に表示されます。

于 2008-10-15T04:17:07.930 に答える