On Wednesday, 23 January 2013 at 16:33:08 UTC, Sarath Kumar wrote:
DMD v2.61; openSUSE 12.1

Source:
-------
libA.d:

module libA;

extern (C)
{
        struct Opaque;

        Opaque* getObject();

        void doSomething(Opaque *);
}
----------
libB.d:

module libB;

extern (C)
{
        struct Opaque;

        void doAction(Opaque *);
}
-----------
bug.d

import libA, libB;

int main(string[] args)
{
        auto opaque = libA.getObject();
        libA.doSomething(opaque); // this is okay
libB.doAction(opaque); // but this is not, compiler error here
        return 0;
}

When I compile the above files, I get the below error.
$ rdmd bug.d
bug.d(7): Error: function libB.doAction (Opaque*) is not callable using argument types (Opaque*) bug.d(7): Error: cannot implicitly convert expression (opaque) of type Opaque* to Opaque*

If I do an explicit cast, libB.Opaque*, for opaque in line 7, bug.d, I get completely different set of errors.

$ rdmd bug.d
libB.d(5): Error: struct libB.Opaque unknown size
libB.d(5): Error: struct libB.Opaque no size yet for forward reference
libB.d(5): Error: struct libB.Opaque unknown size
libB.d(5): Error: struct libB.Opaque no size yet for forward reference
libA.d(5): Error: struct libA.Opaque unknown size
libA.d(5): Error: struct libA.Opaque no size yet for forward reference

Can someone please tell me the right way to pass an opaque object between module's functions.

--
Thanks,
Sarath

You have hit one of the D problems regarding extern(). The first problem is that extern(C)-declared objects inside functions are still mangled, the other problem is that extern(C) Type var; still creates var object, unlike C does (except when Type is a function pointer).

The following D program is compiled and linked:

extern(C) int i;

void main()
{
        i = 0;
}

However, a C equivalent would result in linking error due to unresolved i reference.

So, what you are really doing is unusable. By the way, doing this way you are actually defining two different structs, libA.Opaque and libB.Opaque. Compiler is right in this case, because these types are incompatible, but it should print full names to show the difference explicitly.

If you are working with C library, you can use following scheme:
------main.d------------
extern extern(C) struct Opaque;

extern extern(C) Opaque* getObject();


void main()
{
        Opaque* ptr = getObject();
}
-----struct.c-----------
struct Opaque
{
        int i;
        double d;
};

struct Opaque op;

struct Opaque* getObject()
{
        return &op;
}
------------------------

and if you are using D code, you should use .di files.

Reply via email to