September 07, 2022

On Tuesday, 6 September 2022 at 16:56:16 UTC, Steven Schveighoffer wrote:

>

So generating a static binding allows you to both avoid lots of boilerplate work, but also allows you to get a complete binding for the things that importC cannot do.

Ah you mean actually auto-generate bindings so you can save these somewhere so they're more visible (e.g. to IDEs and such)? Yeah that's a neat idea too.

September 07, 2022

On Tuesday, 6 September 2022 at 16:53:16 UTC, ryuukk_ wrote:

>

That's pretty interesting, and it showcase the power and capabilities of ImportC, nice!

Few notes

  • std.meta/std.traits = bloated and slow, i suggest sticking to plain __traits and copy/paste the few(2-3) functions that you need

Yeah this is the unfortunate thing with traits. If you want to make the code example look neat, you use std.traits. But if you want to make it fast, use __traits or is(typeof( tricks.

I wanted the example to be easily understood (and I hacked this in about an hour).

September 07, 2022

On Tuesday, 6 September 2022 at 16:28:18 UTC, Steven Schveighoffer wrote:

>

Still doesn't help with #defines though...

I think Walter is working on it: https://forum.dlang.org/post/t5p5ho$1mmc$1@digitalmars.com

September 07, 2022

On Tuesday, 6 September 2022 at 16:03:03 UTC, Andrej Mitrovic wrote:

>

There is a really cool benefit to having the ImportC feature in the language. It enables us to dynamically bind to C libraries without having to write any bindings code by hand!

There are some quirks though. For example the code will try to load this as if it were a function:

typedef int PaStreamCallback(
    const void *input, void *output,
    unsigned long frameCount,
    const PaStreamCallbackTimeInfo* timeInfo,
    PaStreamCallbackFlags statusFlags,
    void *userData );

But it's actually just a typedef for a callback.

September 07, 2022

On Wednesday, 7 September 2022 at 05:29:31 UTC, Andrej Mitrovic wrote:

>

On Tuesday, 6 September 2022 at 16:50:16 UTC, Paul Backus wrote:

>

Haven't tested, but I think you may be able to simplify this by replacing

FuncType!(__traits(getMember, Module, member))

with

typeof(&__traits(getMember, Module, member))

...which would let you eliminate the FuncType template entirely.

Already tried that, but it doesn't work. Maybe it's just a bug in the backend.

I'd say it's definitely a bug of some kind. This simplified example worked for me:

--- lib.c
int f(int x) { return x + 1; }

--- app.d
import lib;

typeof(&__traits(getMember, lib, "f")) fptr;
pragma(msg, typeof(fptr)); // extern (C) int function(int x)
September 07, 2022

On Wednesday, 7 September 2022 at 13:23:51 UTC, Paul Backus wrote:

>

I'd say it's definitely a bug of some kind. This simplified example worked for me:

--- lib.c
int f(int x) { return x + 1; }

--- app.d
import lib;

typeof(&__traits(getMember, lib, "f")) fptr;
pragma(msg, typeof(fptr)); // extern (C) int function(int x)

Reduced example:

--- lib.c
int foo( void );
typedef int Bar(const void *input);

--- main.d
import lib;

import std.meta;
import std.traits;

template FuncType(alias symbol) {
    alias FuncType = typeof(&symbol);
}

template GetFunctionList(alias Module) {
    alias GetFunctionList = AliasSeq!();
    static foreach (idx, member; __traits(allMembers, Module)) {
        static if (isFunction!(__traits(getMember, Module, member))) {
            GetFunctionList = AliasSeq!(GetFunctionList, typeof(&__traits(getMember, Module, member)));
        }
    }
}

alias X = GetFunctionList!lib;
void main() { }

Running:

$ dmd lib.c main.d

main.d(14): Error: `extern (C) int(const(void)* input)` is a `function` definition and cannot be modified
main.d(19): Error: template instance `main.GetFunctionList!(lib)` error instantiating

As mentioned in the previous reply it seems that a function typedef trips it up. If there was a way to filter it out, that'd be great.

September 07, 2022

On Wednesday, 7 September 2022 at 15:35:29 UTC, Andrej Mitrovic wrote:

>

As mentioned in the previous reply it seems that a function typedef trips it up. If there was a way to filter it out, that'd be great.

I think the root of the problem here is that std.traits.isFunction does not do exactly what you're assuming it does. Specifically, it evaluates to true for both function symbols and function types:

import std.traits;

void fun() {}
static assert(isFunction!fun); // ok
static assert(isFunction!(typeof(fun))); // also ok!

In order to filter for just function symbols, you need to use a more elaborate test:

        static if (
            is(typeof(&__traits(getMember, Module, member)) PtrType)
            && isFunctionPointer!PtrType
        ) {
            GetFunctionList = AliasSeq!(GetFunctionList, PtrType);
        }

This first checks whether you can take the member's address, and then, if you can, checks whether the type of that address is a function pointer. If I use the condition above in your reduced example, it compiles successfully, and the resulting list does not include the typedef.

September 07, 2022

On Wednesday, 7 September 2022 at 16:05:44 UTC, Paul Backus wrote:

>

On Wednesday, 7 September 2022 at 15:35:29 UTC, Andrej Mitrovic wrote:

>

As mentioned in the previous reply it seems that a function typedef trips it up. If there was a way to filter it out, that'd be great.

I think the root of the problem here is that std.traits.isFunction does not do exactly what you're assuming it does. Specifically, it evaluates to true for both function symbols and function types

Ah yes, that makes sense. I haven't used traits in a long time, shows how rusty I am with them. Thanks for the tips!~

1 2
Next ›   Last »