0
votes

I'm trying to use a third party .net dll in C++Builder (10.3).

I create a .tlb file for the dll with regasm.exe. Then I go to 'Import a Type Library' and choose the .tlb that has been registered, and then choose to install into a new package.

When building the package, I get errors in the generated file mscorlib_TLB.h (I have no experince of .net, but I understand mscorlib is a base class needed in .net).

Here are some of the error messages and the source lines:

[bcc32c Error] mscorlib_TLB.h(2321): declaration of anonymous struct must be a definition:

  interface DECLSPEC_UUID("{84E7AC09-795A-3EA9-A36A-5B81EBAB0558}") _Nullable;

[bcc32c Error] mscorlib_TLB.h(2322): expected a type:

typedef TComInterface<_Nullable, &IID__Nullable> _NullablePtr;

[bcc32c Error] mscorlib_TLB.h(4426): C++ requires a type specifier for all declarations:

typedef _Nullable Nullable;

[bcc32c Error] mscorlib_TLB.h(4426): nullability specifier '_Nullable' cannot be applied to non-pointer type 'int':

typedef _Nullable Nullable;

[bcc32c Error] mscorlib_TLB.h(12060): declaration of anonymous struct must be a definition:

interface _Nullable  : public IDispatch

[bcc32c Error] mscorlib_TLB.h(22823): expected ')' mscorlib_TLB.h(22822): to match this '(':

  virtual HRESULT STDMETHODCALLTYPE MarshaledObject(VARIANT obj/*[in]*/, 
                                                    Mscorlib_tlb::_ObjRef* or/*[in]*/) = 0; // [-1]

I've also tried to import the .net dll with 'Import .NET Assembly', but that gives me 'OLE Error'.

Any idea what I'm missing?

EDIT:

I wrote my own class library (I've never used C# before, my hope was that I could use a .NET dll in C++Builder without that) and tried to import it to C++Builder. But I get exactly the same errors for the (in C++Builder) generated mscorlib_TLB.h. This library though, I'm able to import with the selection 'Import .NET Assembly'.

using System;
using System.Runtime.InteropServices;

namespace ClassLibraryTest
{
    [ClassInterface(ClassInterfaceType.None)]
    public class TestKlass
    {
        public int Funkt1(int x)
        {
            x = x + 1;
            return x;
        }

        public int Funkt2(int x)
        {
            x = x + 2;
            return x;
        }

        public string Funkt3(string str)
        {
            return "str:" + str;
        }
    }
}

I've tried the tool Crosstalk from Atozed, for using .NET assemblies in C++Builder. There I'm able to import a .NET dll. But only the library I wrote, the desired dll gives me errors there as well. My plan now is to write my own (clean) interface in C#, use it to talk with the desired dll and import to C++Builder via Crosstalk.

1
Your compiler just can't handle mscorlib.tlb. Requiring it to use your .NET assembly is not pretty and should always be avoided. You need to go back to your C# code and make it better. We can't see it but you need to declare the interface explicitly and make your C# class [ClassInterface(ClassInterfaceType.None)]. - Hans Passant
Thanks! I don't have the source code for the dll, I can't change it. I've now tried with a class library I wrote myself, see edited post above. - Tomas

1 Answers

0
votes

I have run into this problem as well.

The problem is that mscorlib has a Nullable interface that is declared as _Nullable in the mscorlib_TLB.h file. _Nullable is also a C++17 type specifier and so the compiler doesn't recognize it as a definition.

At least in C++Builder version 10.3.2, there is a fix for this. If you re-import with 10.3.2 this will work and you can avoid the expense of the AtoZed tool if you don't need the other features.

There is an import mapping file in the \bin folder of Rad Studio, tlibimp.sym. The 10.3.2 maps _Nullable to _ Nullable _ so that it won't interfere with C++17 syntax. You can see how to edit that file in the Embarcadero documentation here.

I have also found that I need to write clean C# wrappers for C# classes that weren't written intended to be imported. An example was Crystal Reports.