1

In Delphi 7, I'm trying to read some C# .Net public struct constants using COM.

I can't seem to get the syntax right.

Delphi code

I haven't found any way to write code that will even compile against extracted TLB.pas file. This code fails to compile with the error: "Object or class required"

   S := ItemFieldIdentifier.AverageMarketPrice;  

So, even though the C# programmer tells me that this isn't an instantiatable object, the TLB has a constructor for this type, so I figured I try instantiating. This code failed to compile with the error "Undeclared identifier":

   var
     ItemFieldIdentifier1: ItemFieldIdentifier;
     ...
     ItemFieldIdentifier1 :=  CoItemFieldIdentifier.Create;
     S := ItemFieldIdentifier1.AverageMarketPrice;  

Is there a way for me to access these constants via COM, or does the C# programmer need create a instantiatable object that I can create and then access?

C# code

    public struct ItemFieldIdentifier
    {
        ...
                    public static readonly string AverageMarketPrice = "AMP";
        ...

Then, in C#, they have codes a com interop layer

    public class ItemFieldIdentifier
    {
       public string AverageMarketPrice
       {
            get
            {
                 return xxx.Public.ItemCat.ItemFieldIdentifier.AverageMarketPrice; // <-- this is getting the value from the struct.
    }

TLB File

  DIID__ItemFieldIdentifier: TGUID = '{667FB47F-6394-4ED6-842B-7581184B4138}';
  IID__ItemFieldIdentifier_2: TGUID = '{FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}'
  CLASS_ItemFieldIdentifier: TGUID = '{3A9E41E3-A509-483B-A212-6A507EA29B5B}';

  _ItemFieldIdentifier = dispinterface;
  _ItemFieldIdentifier_2 = interface;
  _ItemFieldIdentifier_2Disp = dispinterface; 

    ItemFieldIdentifier = _ItemFieldIdentifier_2;

    // *********************************************************************//
    // DispIntf:  _ItemFieldIdentifier
    // Flags:     (4096) Dispatchable
    // GUID:      {667FB47F-6394-4ED6-842B-7581184B4138}
    // *********************************************************************//
  _ItemFieldIdentifier = dispinterface
    ['{667FB47F-6394-4ED6-842B-7581184B4138}']
    ...
    property AverageMarketPrice: WideString readonly dispid 45;
    ...

  end;

    // *********************************************************************//
    // Interface: _ItemFieldIdentifier_2
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // GUID:      {FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}
    // *********************************************************************//
      _ItemFieldIdentifier_2 = interface(IDispatch)
        ['{FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}']
      end;


    // *********************************************************************//
    // Interface: _ItemFieldIdentifier_2
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // GUID:      {FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}
    // *********************************************************************//
      _ItemFieldIdentifier_2 = interface(IDispatch)
        ['{FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}']
      end;

    // *********************************************************************//
    // DispIntf:  _ItemFieldIdentifier_2Disp
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // GUID:      {FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}
    // *********************************************************************//
      _ItemFieldIdentifier_2Disp = dispinterface
        ['{FBF4AD9B-38B5-3856-ADAC-57DB3198BBE7}']
      end;

    // *********************************************************************//
    // The Class CoItemFieldIdentifier provides a Create and CreateRemote method to          
    // create instances of the default interface _ItemFieldIdentifier_2 exposed by              
    // the CoClass ItemFieldIdentifier. The functions are intended to be used by             
    // clients wishing to automate the CoClass objects exposed by the         
    // server of this typelibrary.                                            
    // *********************************************************************//
      CoItemFieldIdentifier = class
        class function Create: _ItemFieldIdentifier_2;
        class function CreateRemote(const MachineName: string): _ItemFieldIdentifier_2;
      end;
2
  • This doesn't make a lot of sense. The .tlb you posted won't compile. Multiple definitions of _ItemFieldIdentifier_2. Could you double check what you posted is accurate. Commented Feb 24, 2014 at 22:32
  • Thanks for taking a stab at this, David. I know how important it is to post real code that compiles (especially when I hope you'll take a look at it! :-)) but the entire .pas file was too big to post here. I posted what I thought was an validly pruned version. Guess not though. Remy got me going though. Thanks again. Commented Feb 25, 2014 at 2:12

2 Answers 2

1

So, even though the C# programmer tells me that this isn't an instantiatable object, the TLB has a constructor for this type, so I figured I try instantiating. This code failed to compile with the error "Undeclared identifier"

That is odd, because ItemFieldIdentifier is clearly defined (it is an alias for _ItemFieldIdentifier_2).

CoItemFieldIdentifier.Create() returns an _ItemFieldIdentifier_2, so you might try declaring your variable as that. However, _ItemFieldIdentifier_2 does not have any members declared. So, assuming ItemFieldIdentifier_2 derives from ItemFieldIdentifier on the C# side, you might try doing a cast from _ItemFieldIdentifier_2 to _ItemFieldIdentifier on the Delphi side:

var
  ItemFieldIdentifier1: _ItemFieldIdentifier;
...
ItemFieldIdentifier1 := CoItemFieldIdentifier.Create as _ItemFieldIdentifier;
S := ItemFieldIdentifier1.AverageMarketPrice;  

Or:

var
  ItemFieldIdentifier1: _ItemFieldIdentifier_2;
...
ItemFieldIdentifier1 := CoItemFieldIdentifier.Create;
S := (ItemFieldIdentifier1 as _ItemFieldIdentifier).AverageMarketPrice;  
Sign up to request clarification or add additional context in comments.

1 Comment

Something is very wrong if this is the solution. Is the .tlb importer getting it wrong. If so I would deal with the issue by fixing the interface declarations so that the code could be written without a cast.
0

The vtRecord OLE type is not handled by Delphi 7. This type matches C# struct type.

I suspect you should use a C# class marked as COMVisible=True as a data object, to be accessed from Delphi.

Or you may try to generate the TLB .pas file using a more recent TLBEXP tool. I found out the latest versions are able to handle such struct types correctly.

1 Comment

Good suggestion, Arnaud, to try a more recent version of Delphi. I just tried that, hopeful, but it didn't resolve the problem. Thanks for the suggestion though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.