Can anyone help me with C macro? See full descript...
# kotlin-native
r
Can anyone help me with C macro? See full description in thread.
Docs describe usage like:
Copy code
headers = library/base.h

---

static inline int foo(int arg) {
    return FOO(arg);
}
My code. Macro definition in external
.h
file
Copy code
#define INI_STR(name) zend_ini_string_ex((name), sizeof(name)-1, 0, NULL)
Definition in
.def
file
Copy code
static inline char* php_helper_ini_string(char* arg) {
    return INI_STR(arg);
}
Using in
.kt
Copy code
fun getStringIni(name:String) = php_helper_ini_string(name.cstr)?.toKString()?:"WARRRRGGGGHHHHH"
In fact, this code always return NULL (It is default behavior of
zend_ini_string_ex
for unknown argument.) If I explict writing
return INI_STR("somename");
in
.def
, then result is correct. What I doing wrong?
m
sizeof(char*) == 8
(on 64bit system) so you always use first 7 chars. It should be something like this:
Copy code
static inline char* php_helper_ini_string(char* name) {
    return zend_ini_string_ex(name, strlen(name), 0, NULL);
}
r
Unfortunately, in this case I need to use macro. Because of backward compatibility. Do you have any suggestions about avoid this problem?
m
That macro assumes C string constant as parameter, so you cannot use Kotlin string constant - it is not constant in C.
If you want to pass stable pointer to C string from Kotlin, I know only one way: add in`.def`
noStringConversion = php_helper_ini_string
Then from Kotlin you can call it as
php_helper_ini_string(immutableBinaryBlobOf('A'.toShort, 0).asCPointer(0))
But it is
ImmutableBinaryBlob
, not
String
.
s
In fact, this code always return NULL (It is default behavior of
zend_ini_string_ex
for unknown argument.)
What do you mean by “unknown argument”?
m
Copy code
ZEND_API char *zend_ini_string_ex(char *name, size_t name_length, int orig, zend_bool *exists)
{
	zend_ini_entry *ini_entry;

	ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
	if (ini_entry) {
		if (exists) {
			*exists = 1;
		}

		if (orig && ini_entry->modified) {
			return ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL;
		} else {
			return ini_entry->value ? ZSTR_VAL(ini_entry->value) : NULL;
		}
	} else {
		if (exists) {
			*exists = 0;
		}
		return NULL;
	}
}
r
In this case - any value that not in the ini-storage. If
somename
exists in storage then this function returns it's value otherwise returns null
Thank Mike, I'll go try.
m
So it dont have to be stable pointer, your original code should work, if just replace
sizeof
to
strlen
.
r
Yes, it must work with
strlen
, but it's external library function and I can't change definition of macro 😞
s
This macro looks pretty simple. Isn’t it possible to write proper Kotlin function instead?
r
Svyatoslav, this macro used for backward compatibility. No guarantee that this macro keeps unchanged in future.
s
Yes. But its current implementation is supposed to remain valid in future, otherwise this library would not have binary compatibility when used from C.
a
It's rare case. 🙂 I writing "framework" for PHP-extension development with KN. It must be compatible with various version of zend api. But almost all zend api's functions have recomended access through macro.
o
Why cannot you append all compile-time known strings to the
.def
file and use C macros from there?
r
Uhhh... It is not private one-time project. I make something like proxy between KN and zend libraries. Main purpose (excluding education) is create tools for php-extension development with KN. All user space php-functions will be described by dsl and connected to KN functions, where defined those compile-time strings. User manual with instructions like "define all used string constants in separated .def file" smell a little. Other way is parse
.kt
sources and autogenerate
.def
, but...
o
So, the I assume solution suggested by Mike with explicit strlen() would be the best one