1

My C# code has a struct which I am exporting to COM. The properties of this struct are coming through with strange names that aren't even valid syntax in VB6, so they cannot be accessed.

Is there some way to get these to export with normal, usable names? Am I missing an attribute or something?


The format of the name in COM / VB6 is:

<original_name>k__BackingField

where only the original_name part was in my C# code.

I can only see these crazy property names in the VB6 Object Browser, Intellisense won't show it.

Here's the (slightly sanitized) code which is being built:

[Guid("....")]
[ComVisible(true)]
public struct MyStruct
{
    public string StringA { get; set; }
    public string StringB { get; set; }

    public MyStruct(string a, string b)
    {
        StringA = a;
        StringB = b;
    }

    ... // some other methods, no fields or properties
}

and for good measure here is the IDL that gets generated:

typedef [uuid(....), version(1.0), custom(xxxx, MyNamespace.MyStruct)]
struct tagMyStruct {
    LPSTR <StringA>k__BackingField;
    LPSTR <StringB>k__BackingField;
} MyStruct;

as shown by OleView. I can see it contains the same k__BackingField as noted above. So it seems these names are coming from the C# typelib export process.

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
  • 1
    You've got the [answer](https://stackoverflow.com/a/57827805/11683). You are using auto-implemented properties. Use fields directly instead. – GSerg Sep 06 '19 at 20:07
  • @GSerg so unlike classes the properties of a struct don't get exported? Is that correct? – StayOnTarget Sep 06 '19 at 20:10
  • COM `struct` cannot contain methods or properties. [The grammar](https://learn.microsoft.com/en-us/windows/win32/midl/struct) only allows for fields. – GSerg Sep 06 '19 at 20:18
  • @GSerg but a C# class similarly exported doesn't have this problem, that's what I meant. The COM field names match the C# class names fine in that scenario. – StayOnTarget Sep 06 '19 at 20:19
  • Because classes (actually, interfaces), [are allowed](https://learn.microsoft.com/en-us/windows/win32/midl/dispinterface) to have properties. – GSerg Sep 06 '19 at 20:23
  • Auto properties in C# are syntax sugar, the CLR doesn't support anything like it. So you got to see how the C# compiler did it. The semantics of a struct in COM is the same as in the C language, just fields with no support for properties or methods. So all the type library exporter can do is expose those auto-generated fields. This is dangerous of course, you normally use auto properties so that some day you can easily switch to a more involved getter or setter. They are never going to get called. – Hans Passant Sep 07 '19 at 09:54
  • And much worse, a significant implementation detail of struct is that the client code has to figure out at what offset it should read a field value. Related to the "packing" rules that the compiler used, compare to StructLayoutAttribute.Pack. VB6 does that properly, it uses IRecordInfo to find out. This is not fast, at all. You really do favor a class. Only an out-of-process server might consider it, the marshaling is faster than the round-trips for each field, but they are very hard to write correctly in C# so not much of a consideration. – Hans Passant Sep 07 '19 at 10:00

1 Answers1

4

public string StringA { get; set; } is only a short form of the following

private string _stringA_BackingField;
public string StringA
{
  get { return _stringA_BackingField; }
  set { _stringA_BackingField = value; }
}

And since COM structs only contain fields and no properties you will see the backing field. Your example should work if you change the code to the following:

[Guid("....")]
[ComVisible(true)]
public struct MyStruct
{
    public string StringA;
    public string StringB;
}

By definition the struct type is a value type that is typically used to encapsulate small groups of related variables.

If you want to provide properties or methods you need to use a class. You find more information about structs here:

  • But I guess the bottom line is that TLBEXP is creating COM structs with unusable names. The fact that its an automatic backing field doesn't excuse that. TLBEXP could be much smarter here and do something more useful. – StayOnTarget Sep 10 '19 at 18:28