【问题标题】:incompatible types in Delphi 7Delphi 7 中的不兼容类型
【发布时间】:2014-06-16 07:21:53
【问题描述】:

我已按如下所述进行了此操作:

使用 CDO_TLB、ADODB_TLB; _Stream 在 ADODB_TLB 单元(活动数据对象)中定义。 IMessage,> I 配置在 CDO_TLB 单元(协作数据对象)中。如果尚未创建使用 导入类型库如下并创建:CDO_TLB = C:\WINDOWS\system32\cdosys.dll
ADO_TLB = C:\Program Files\Common Files\System\ado\msadoxx.dll - xx 版本号

现在我收到以下错误:

    [Fehler] Unit1.pas(1650): Inkompatible Typen: 'ADODB_TLB.TStream' und 'Classes.TStream'
    [Fehler] Unit1.pas(1651): Inkompatible Typen: 'ADODB_TLB.TStream' und  'Classes.TStream'
    [Fehler] Unit1.pas(1655): Inkompatible Typen: 'Classes.TStream' und 'ADODB_TLB.TStream'
    [Fehler] Unit1.pas(1656): Inkompatible Typen: 'Classes.TStream' und 'ADODB_TLB.TStream'
    [Fehler] Unit1.pas(1720): Inkompatible Typen: 'ADODB_TLB.TStream' und 'Classes.TStream'
    [Fehler] Unit1.pas(1724): Inkompatible Typen: 'Classes.TStream' und 'ADODB_TLB.TStream'

在此声明:

    SpecStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SpecSheet'), bmRead);
    SaftyStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SaftySheet'), bmRead);

我知道我已经通过导入 TLB 更改了类型库。 但是我怎样才能仍然使用这两个类?

这是我的代码,仅需要的部分: (用 //we 表示错误的行。)

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, Grids, DBGrids, ExtCtrls, DBCtrls, MemDS, DBAccess,
      MyAccess, MyDacVcl, StdCtrls, frxClass, frxDesgn, frxDBSet, frxExportPDF,
      jpeg, ComCtrls, SBCookieMgr, SBSimpleSSL, SBHTTPSClient, SBConstants,
      SBHTTPCRL, SBHTTPOCSPClient, SBHTTPCertRetriever,  SBX509,
      SBSSLClient, SBTypes, SBUtils, SBCustomCertStorage, SBCertValidator,
      OleCtrls, SHDocVw ,Wininet, PDFSplitMerge_TLB,
      ActiveX, // IMalloc
      ShlObj, SBArcBase, SBArcZip, // CSIDL_-Konstanten
      ShellAPI; // SHGetSpecialFolderLocation() und SHGetPathFromIDList()


    type
      ...

    implementation

    {$R *.dfm}

    uses  RegExpr, CDO_TLB, ADODB_TLB;

    ..

    procedure TForm1.Button7Click(Sender: TObject);
    var
      oldTabSheet: TTAbSheet;
      SpecStream, SaftyStream: TStream;

      MyAN: string;
      MyLief: String;

    begin
      oldTabSheet := pageControl1.ActivePage;
      pageControl1.ActivePage:= TabSheet5;
      //WebBrowser1.Navigate(PrgDirName+'\laborbedarf.pdf');
      //WebBrowser1.Quit;
      //Radiobutton1.Checked:=NOT(radiobutton1.Checked);
      //Radiobutton2.Checked:=NOT(radiobutton2.Checked);

        MyAN := MyQuery1.FieldByName('ArtikelNummer').AsString;
        MyLIEF := MyQuery1.FieldByName('Lieferant').AsString;
        if NOT((MyAN = NULL) or (MyAN = ''))  then
          begin
          (* ---------------------------------------------------------- LIEFERANT 1 ---*)

          if MyLIEF = DBGrid1.Columns[11].PickList[0] then
            begin
            MyQuery9.SQL.Text:='select * from stoff WHERE   RecID = :Old_RecID';
            MyQuery9.ParamByName('Old_RecID').AsInteger := MyQuery1.FieldByName('RecID').AsInteger;
            MyQuery9.Execute;
    //we        SpecStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SpecSheet'), bmRead);
    //we        SaftyStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SaftySheet'), bmRead);
            MyStream2S := TMemoryStream.Create;
            MyStream3S := TMemoryStream.Create;
            MyStream2S.Clear; MyStream3S.clear;
    //we        MyStream2S.LoadFromStream(SaftyStream );
    //we        MyStream3S.LoadFromStream(SpecStream );

            if RadioButton1.Checked then
              begin
                try

                  DeleteFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  MyStream2S.SaveToFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  WebBrowser1.Navigate(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  Radiobutton1.Checked:= false;
                  Radiobutton2.Checked:= true;

                except
                  end;

                try
                  DeleteFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  MyStream3S.SaveToFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  WebBrowser1.Navigate(GetTempDirectory+'Spezifikation_tmp.pdf');
                  Radiobutton1.Checked:= true;
                  Radiobutton2.Checked:= false;


                except
                  end;

              end
            else if RadioButton2.Checked then
              begin
                try

                  DeleteFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  MyStream3S.SaveToFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  WebBrowser1.Navigate(GetTempDirectory+'Spezifikation_tmp.pdf');
                  Radiobutton1.Checked:= true;
                  Radiobutton2.Checked:= false;

                except
                  end;

                try

                  DeleteFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  MyStream2S.SaveToFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  WebBrowser1.Navigate(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  Radiobutton1.Checked:= false;
                  Radiobutton2.Checked:= true;

                except
                  end;

              end;


            end
            (* ---------------------------------------------------------- LIEFERANT 2 ---*)
          else
            if MyLIEF = DBGrid1.Columns[11].PickList[1] then

            begin
            MyQuery9.SQL.Text:='select * from stoff WHERE   RecID = :Old_RecID';
            MyQuery9.ParamByName('Old_RecID').AsInteger := MyQuery1.FieldByName('RecID').AsInteger;
            MyQuery9.Execute;
            //SpecStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SpecSheet'), bmRead);
    //we        SaftyStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SaftySheet'), bmRead);
            MyStream2S := TMemoryStream.Create;
            MyStream3S := TMemoryStream.Create;
            MyStream2S.Clear; MyStream3S.clear;
    //we        MyStream2S.LoadFromStream(SaftyStream );
            //MyStream3S.LoadFromStream(SpecStream );

           Radiobutton1.Checked:= false;
           Radiobutton2.Checked:= true;

            if RadioButton2.Checked then
              begin
                try

                  DeleteFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  MyStream3S.SaveToFile(GetTempDirectory+'Spezifikation_tmp.pdf');
                  if Filesize(GetTempDirectory+'Spezifikation_tmp.pdf') > 5 then
                    WebBrowser1.Navigate(GetTempDirectory+'Spezifikation_tmp.pdf')
                  else
                    WebBrowser1.Navigate(PrgDirName+'\PDFLeer.pdf');

                  Radiobutton1.Checked:= true;
                  Radiobutton2.Checked:= false;

                except
                  ShowMessage(' Kann PDF nicht anzeigen, wurde es nicht geladen weil nicht verfügbar?');
                  end;

                try

                  DeleteFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  MyStream2S.SaveToFile(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf');
                  if Filesize(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf') > 5 then
                    WebBrowser1.Navigate(GetTempDirectory+'Sicherheitsdatenblatt_tmp.pdf')
                  else
                    WebBrowser1.Navigate(PrgDirName+'\PDFLeer.pdf');

                  Radiobutton1.Checked:= false;
                  Radiobutton2.Checked:= true;

                except
                  ShowMessage(' Kann PDF nicht anzeigen, wurde es nicht geladen weil nicht verfügbar?');

                  end;

              end;


            end   ;

        //MyQuery1.Next;
        MyStream3S.Clear;
        MyStream2S.Clear;
        MyStream3S.free;
        MyStream2S.free;

        end
      else
        begin
        ShowMessage('Kein PDF in DB gefunden!');
        end;




    end;

【问题讨论】:

  • 我猜你有两个单元声明了`TStream.但是您没有以可读的方式显示代码,也没有告诉我们任何变量是什么类型。您可以通过显示完整的代码来提供帮助,或者至少足以让我们了解所有内容。
  • 我想集成这个过程:[link]stackoverflow.com/questions/12690331/…@David:在我在uses子句中添加ADODB_TLB之前它工作正常。
  • 我建议您重新阅读我的评论并按照建议编辑问题
  • @SertacAkyuz:非常感谢,现在我可以编译了。
  • @WalterSchrabmair 我建议你重新考虑你所有的尝试......除了。这不是进行异常处理的方法。你所做的只是隐藏你的错误。您还应该使用 try..finally 来保护资源。最后,您需要将代码拆分为更小的函数。

标签: delphi


【解决方案1】:

显然,您在ADODB_TLB 单元中有第二个TStream 声明,并且当您在同一单元中同时使用ADODB_TLBClasses - TStream 将从最后一个声明的单元开始使用。你可以解决这个问题:

  1. 通过明确使用所需单元中的TStream

    var
    S1: ADODB_TLB.TStream;
    S2: Classes.TStream;

  2. 通过将 TStream 重命名为更独特的名称,例如 ADODB_TLB.TStreamADODB_TLB.TADOStream。我更喜欢这个 方法。您可以通过重新导入 ADODB_TLB 并指定类型来做到这一点 重命名TStream(在导入向导中选择)

【讨论】:

  • 1 的变体是在导致冲突的单元中使用type TStream = ADODB_TLB.TStream;
  • 恕我直言,最好避免类型重新声明和在不同单元中声明多个具有相同名称的类型。它减少了误解和错误的机会。
  • 第 2 点通常是个好主意,但在这种情况下并非如此。 ADODB_TLB 随 Delphi 一起提供,供ADODB.pas 使用。更改它可能会破坏该单位。
  • 非常感谢,比预期更多的信息 - 所以让我改进!
  • 我想要解决方案 1,因为 ADOTLB 不是我创建的。我知道我仍然可以改进!
【解决方案2】:

问题是你的接口使用了Classes,它定义了TStream
而且您的实现使用ADODB_TLB,它也定义了TStream
注意:正如 Sertac 指出的那样,如果您在interface 部分,但有ADODB_TLB 之后 Classes

因此,每当您在设备的接口部分使用TStream 时,您就是在使用Classes.TStream。但在实施部分,那将是ADODB_TLB.TStream,这就是您收到错误的原因。当您在另一个单元中调用使用不同类型的TStream 的例程时也会发生错误(例如返回Classes.TStreamCreateBlobStream)。

//You declared SaftyStream in the implementation section, so it is ADODB_TLB.TStream.
//But CreateBlobStream returns a Classes.TStream.
//So they are incompatible.
SaftyStream := MyQuery9.CreateBlobStream(MyQuery9.FieldByName('SaftySheet'), bmRead);

//You don't show where you declare MyStream2S.
//I assume interface section, so it is Classes.TStream.
//Classes.TStream.LoadFromStream expects to be given a Classes.TStream
//But SaftyStream is ADODB_TLB.TStream, which is incompatible.
MyStream2S.LoadFromStream(SaftyStream );

在解决这个问题时,您需要决定的第一件事是您真正想要使用两个TStreams 中的哪一个? (我怀疑Classes 中的那个。正如Sertac 指出的那样,CreateBlobStream 返回一个Classes.TStream,所以你应该使用那个。)

选项

  • 首先考虑是否真的需要使用ADODB_TLB? Delphi 已经在ADODB.pas 中有这个类型库的包装器。如果您可以使用它,您将遵循“更传统”的 Delphi 范例。

  • 如果您必须直接针对 ADO 进行编码,那么我建议您将 uses ADODB_TLB 移动到接口部分,之前 uses Classes。这样TStream(来自Classes)的最新定义将适用于您的整个单位。

  • 您还可以引用具有完全限定名称的类型,如VitaliyG's answer 的第 1 点。 IE。 Classes.TStream

  • 但是,在这种情况下,我不建议像他回答的第 2 点那样重命名 TStream。原因是这些是 Delphi 附带的单元,而其他单元依赖于它们。但是,如果命名冲突是在您自己的单位中,那么我肯定会建议选择更具体的名称来区分类型。如果类型确实是相同的,那么也许您应该将它们合并到一个共享的第三单元中。


附录

您在评论中提到:

我想集成这个过程:Create *. Mht-file (Web Archive) 在我在 uses 子句中添加 ADODB_TLB 之前它运行良好。

这解释了您添加该单元的原因。但是,考虑到命名冲突以及可能引起不必要的麻烦:我建议您将功能隔离到一个小的专用单元中(例如MHTBuilder.pas)。

  • 那么您的单元将不需要使用ADODB_TLB(它将被 MHTBuilder 使用)。
  • 您的单位将改用MHTBuilder
  • 并调用一个简单的函数来构建 MHT 文件。

这与我关于您需要将代码拆分为更小的函数的评论密切相关。将事物分解成更小的部分可以更容易地管理复杂性。基本上,您应该避免尝试将所有功能和选项集中到一个庞大的方法中(就像您所做的那样)。

【讨论】:

  • 要么你的问题识别是错误的,要么你的措辞给人留下了这样的印象。即使两个单位在interface中都使用过,只要在'classes'之后使用'adodb_tlb',也会出现错误。那是因为“CreateBlobStream”返回一个“classes.TStream”。 (顺便说一句,毫无疑问,它是打算使用的类的流(如果这不明显,也可以参考问题的 cmets)。
  • 感谢@SertacAkyuz 我已经更新了我的答案以澄清。
猜你喜欢
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多