www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Translating C precompiler macros to D

reply solidstate1991 <laszloszeremi outlook.com> writes:
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))							\

	_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.)
Nov 08 2023
parent evilrat <evilrat666 gmail.com> writes:
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))							\

 	_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)(); } ```
Nov 09 2023