digitalmars.D - Package permission and symbol resolution
- Manu via Digitalmars-d (55/55) Apr 22 2014 So I've restructured one of my projects which is a C library bindings,
- John Colvin (9/45) Apr 22 2014 package protection allows access from the current package and
- Manu via Digitalmars-d (12/70) Apr 22 2014 Yeah, this seems like a problem, particularly since precisely what I'm
- Manu via Digitalmars-d (23/31) Apr 22 2014 Well, it worked in some cases...
- Marco Leise (5/6) Apr 23 2014 By the way: What about adding nothrow there?
So I've restructured one of my projects which is a C library bindings, but also with some D-ification. I separated it into 2 parts, the raw binding parts, and the api enhancements, the module structure looks like this: The Raw C binding part: pkg/c/module.d: pkg.c.module; struct ModuleStruct { package: int privateParts; } extern (C) void func(const(char)* pString); And the wrapping layer; public import's the raw C bindings, which is meant to make the C API available too while adding some sugar for convenience. pkg/module.d: pkg.module; public import pkg.c.module; void func(const(char)[] str) { pkg.c.module.func(str.toStringz); } void func2(ref ModuleStruct s) { s.privateParts += 10; } I have a bunch of surprising problems. 1. Error: struct pkg.c.module.ModuleStruct member privateParts is not accessible pkg.module can't access pkg.c.module.ModuleStruct.privateParts. Isn't that what 'package' protection is for? My sugar wrapping module needs to be able to access the private bits of the raw binding module, which I don't want to pollute with sugar directly (since it would ideally be generated by a generator and reflect only a pure C binding). 2. In client code, when I call for instance, func("string".ptr), which has 2 overloads: 'extern (C) void func(const(char)*)' and 'void func(const(char)[])', it doesn't seem to resolve the function correctly: Error: pkg.module.func at pkg\module.d(14) conflicts with pkg.c.module.func at pkg\c\module.d Error: function pkg.module.func (const(char)[] str) is not callable using argument types (immutable(char)*) Obviously, the other overload (pkg.c.module.func) can receive immutable(char)* though, but it just ignores it rather than choosing to call the appropriate overload. What's really weird, is if I pass a string instead: func("string"[]), it picks the other incorrect overload. Error: cannot implicitly convert expression (func("string"[])) of type const(char)[] to const(char)* I've changed lots of random things, but I can't seem to resolve this cleanly. What have I missed? It must be something simple. This must be a common problem. I would imagine basically anyone who wants to add sugar to a C binding would do it this way to avoid polluting of the raw binding code? Is there an alternative recommended practise?
Apr 22 2014
On Tuesday, 22 April 2014 at 08:07:32 UTC, Manu via Digitalmars-d wrote:So I've restructured one of my projects which is a C library bindings, but also with some D-ification. I separated it into 2 parts, the raw binding parts, and the api enhancements, the module structure looks like this: The Raw C binding part: pkg/c/module.d: pkg.c.module; struct ModuleStruct { package: int privateParts; } extern (C) void func(const(char)* pString); And the wrapping layer; public import's the raw C bindings, which is meant to make the C API available too while adding some sugar for convenience. pkg/module.d: pkg.module; public import pkg.c.module; void func(const(char)[] str) { pkg.c.module.func(str.toStringz); } void func2(ref ModuleStruct s) { s.privateParts += 10; } I have a bunch of surprising problems. 1. Error: struct pkg.c.module.ModuleStruct member privateParts is not accessible pkg.module can't access pkg.c.module.ModuleStruct.privateParts. Isn't that what 'package' protection is for?package protection allows access from the current package and subpackages (pkg.c.* in this case), but not to anyone further up the tree (pkg.someModule). It would be nice one could write `protected(packageName)` to have better control over this. The rest of your problems are, I think, explained here: http://dlang.org/hijack.html
Apr 22 2014
On 22 April 2014 19:16, John Colvin via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Tuesday, 22 April 2014 at 08:07:32 UTC, Manu via Digitalmars-d wrote:Yeah, this seems like a problem, particularly since precisely what I'm doing seems intuitive and desirable to me. Are there other patterns to separate the sugar from the raw binding? If the binding is generated, it can't coexist with the sugar or it'll be overwritten each time.So I've restructured one of my projects which is a C library bindings, but also with some D-ification. I separated it into 2 parts, the raw binding parts, and the api enhancements, the module structure looks like this: The Raw C binding part: pkg/c/module.d: pkg.c.module; struct ModuleStruct { package: int privateParts; } extern (C) void func(const(char)* pString); And the wrapping layer; public import's the raw C bindings, which is meant to make the C API available too while adding some sugar for convenience. pkg/module.d: pkg.module; public import pkg.c.module; void func(const(char)[] str) { pkg.c.module.func(str.toStringz); } void func2(ref ModuleStruct s) { s.privateParts += 10; } I have a bunch of surprising problems. 1. Error: struct pkg.c.module.ModuleStruct member privateParts is not accessible pkg.module can't access pkg.c.module.ModuleStruct.privateParts. Isn't that what 'package' protection is for?package protection allows access from the current package and subpackages (pkg.c.* in this case), but not to anyone further up the tree (pkg.someModule). It would be nice one could write `protected(packageName)` to have better control over this.The rest of your problems are, I think, explained here: http://dlang.org/hijack.htmlAh ha! "in order to overload functions from multiple modules together, an alias statement is used to merge the overloads" I've actually read this article before, but I forgot that detail. Cheers mate! :)
Apr 22 2014
On 22 April 2014 21:00, Manu <turkeyman gmail.com> wrote:On 22 April 2014 19:16, John Colvin via Digitalmars-dWell, it worked in some cases... How's this for a great error: Error: fuji.c.MFDebug.MFDebug_Warn at D:\WinDev\fuji\dist\include\d2\fuji\c\MFDebug.d(38) conflicts with fuji.c.MFDebug.MFDebug_Warn at D:\WinDev\fuji\dist\include\d2\fuji\c\MFDebug.d(38) Precisely the same symbol in precisely the same file are apparently in conflict... It seems it all gets confused when a file is imported via multiple indirect means. For instance: B public imports A, B overloads some function in A and must make it explicit using the rule you lank me to: alias finc = A.func; If some client imports B, it is now working as expected; the overload in A and B are both accessible. But let's say there is also C which public imports A. C does not overload anything A, so there's no need for the alias trick. Client imports B and C (but not A). It seems that now A via C is in conflict with A via B, even though B provides the alias to explicitly satisfy the anti-hijacking rule. The same function reachable via C stimulates the anti-hijacking error again even though it was addressed in B where the overload was specified.The rest of your problems are, I think, explained here: http://dlang.org/hijack.htmlAh ha! "in order to overload functions from multiple modules together, an alias statement is used to merge the overloads" I've actually read this article before, but I forgot that detail. Cheers mate! :)
Apr 22 2014
Am Tue, 22 Apr 2014 18:07:21 +1000 schrieb Manu via Digitalmars-d <digitalmars-d puremagic.com>:extern (C) void func(const(char)* pString);By the way: What about adding nothrow there? -- Marco
Apr 23 2014