Translating C precompiler macros to D
evilrat
evilrat666 at gmail.com
Thu Nov 9 09:49:33 UTC 2023
On Wednesday, 8 November 2023 at 20:43:21 UTC, solidstate1991
wrote:
> Here's this precompiler macro from Pipewire, on which many
> important inline functions depend on, like this one:
>
> ```c
> /**
> * Invoke method named \a method in the \a callbacks.
> * The \a method_type defines the type of the method struct.
> * Returns true if the method could be called, false otherwise.
> */
> #define spa_callbacks_call(callbacks,type,method,vers,...) \
> ({ \
> const type *_f = (const type *) (callbacks)->funcs; \
> bool _res = SPA_CALLBACK_CHECK(_f,method,vers); \
> if (SPA_LIKELY(_res)) \
> _f->method((callbacks)->data, ## __VA_ARGS__); \
> _res; \
> })
> ```
>
> So far, the only way out I see is to turn it into a string
> mixin. (SPA_LIKELY is just a needless precompiler macro for
> labeling things.)
Not sure if it will work in real situations, expect memory errors.
Also I used a fixed type, you should use CTFE to cast data to
proper function argument types.
```d
import std.stdio;
bool SPA_CALLBACK_CHECK(T)(const (T)* f, string method, uint
version_)
{
// do some checks...
return true;
}
bool spa_callbacks_call(alias callbacks, alias type, alias
method, uint vers, Args...)(Args)
{
const (type)* _f = cast(type*) callbacks.funcs;
bool _res = SPA_CALLBACK_CHECK(_f, __traits(identifier, method),
vers);
if (_res)
__traits(getMember, _f, __traits(identifier, method))(cast(int)
callbacks.data, Args); // callback call
return _res;
}
// your callback, see pipewire docs for real examples
struct Foo
{
void bar(int x) const { import std.stdio; writeln(x); }
}
// pipewire internals
struct spa_callback
{
const(void)* funcs;
void* data;
}
void main()
{
Foo foo;
// instead of this naive approach you should use provided
initialization method
// but roughly first parameter is pointer to struct of function
pointers
spa_callback cb = { cast(void*) &foo, cast(void*) 42 };
spa_callbacks_call!(cb, Foo, Foo.bar, 0)();
}
```
More information about the Digitalmars-d-learn
mailing list