How to cast Int to unsigned short in Swift - objective-c

I have the following function from the Objective-C library in Swift project:
- (DDHotKey *)registerHotKeyWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags task:(DDHotKeyTask)task {
// ...
}
I'm trying to call this function from Swift via the following code:
hotKeyCenter.registerHotKeyWithKeyCode(
kVK_ANSI_V,
modifierFlags: NSEventModifierFlags.ControlKeyMask.rawValue,
task: { _ in
// ...
}
)
Unfortunately, it gives me the following error:
Missing argument for parameter 'action' in call
However, if I change kVK_ANSI_V to any number like this
hotKeyCenter.registerHotKeyWithKeyCode(
34,
modifierFlags: NSEventModifierFlags.ControlKeyMask.rawValue,
task: { _ in
// ...
}
)
code compiles without any error.
As you know, kVK_ANSI_V defined in the Carbon framework:
var kVK_ANSI_V: Int { get }
As you see, it has an Int type while keyCode parameter of the method has an unsigned short type.
How can I cast Int to unsigned short? Is there any way to fix this error?
Thanks in advance.

You can create an UInt16 from any integer n simply
with UInt16(n). In your case:
hotKeyCenter.registerHotKeyWithKeyCode(
UInt16(kVK_ANSI_V),
modifierFlags: NSEventModifierFlags.ControlKeyMask.rawValue,
task: { _ -> Void in
})

Related

Xamarin binding C library params not working (variadic functions)

I need to use a C library and I got it to work on the emulator easily, but on an arm64 device only with some strange trickery. The issue is that C functions with … (variadic functions) do not pass values correctly from C# to the library.
This is the C function, with ...
cmd_ln_t *
cmd_ln_init(cmd_ln_t *inout_cmdln, const arg_t *defn, int32 strict, ...)
{
va_list args;
const char *arg, *val;
char **f_argv;
int32 f_argc;
va_start(args, strict);
f_argc = 0;
while ((arg = va_arg(args, const char *))) {
++f_argc;
E_INFO("name: %s ", arg);
E_INFO(" retrieving value...");
val = va_arg(args, const char*);
E_INFO("value retrieved. \n");
E_INFO("value: %s \n", val);
if (val == NULL) {
E_ERROR("Number of arguments must be even!\n");
return NULL;
}
++f_argc;
}
va_end(args);
.....................................
I check if the values are correct with the E_INFO()
Approach 1 - The default PARAMS doesn't work:
When I use the following default params expression approuch for c bindings, the ‘arg’ printed in the function shows unknown characters and when ‘val’ is used the function crashes.
[DllImport("__Internal")] public static extern unsafe cmd_ln_t*
cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, params string[] arguments);
Approach 2 - a more elaborate approach works:
When I use the a more elaborate approach everything works, on x86_64 architecture normally but for arm64 with a strange work-around.
the binding expression in a more elaborate approach.
[DllImport("__Internal")]
public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2);
[DllImport("__Internal")]
public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2, string arg3);
[DllImport("__Internal")]
public static extern unsafe cmd_ln_t* cmd_ln_init(cmd_ln_t* inout_cmdln, arg_t* defn, int strict, string arg1, string arg2, string arg3, string arg4);
//etc etc… for x numbers of arguments
The binding works works the following code
// works for x86_64
var cmdPointer = MyBindingLib.cmd_ln_init(null, psArgsPointer, 1,
"-hmm", hmmFolder,
"-dict", dictFile,
"-mmap", "no",
"-kws_threshold", "1e-80",
"-lw", "2.0",
null);
// works for arm64
var cmdPointer = MyBindingLib.cmd_ln_init(null, psArgsPointer, 1,
null, null,
null, null, null,
"-hmm", hmmFolder,
"-dict", dictFile,
"-mmap", "no",
"-kws_threshold", "1e-80",
"-lw", "2.0",
null);
As you see, the x86_64 works normally to get the values to the C library.
But the arm64 version needs to have 5 null values, others half of the values won't make it to the C library (I can check that with the E_INFO function in the C function).
Anyone any idea how to get this Xamarin C binding correct with params or without the 5 prefix null values?
Source is on github
uses c library at sphinxbase
It seems to be expected behavior for arm64 architecture, because of the way arm64 functions are invoked.
Invoking functions in a arm64 library that use ...) at the end, you have to take into account that the first 8 argument spots are for 'normal' arguments, then optionally the variable/params can start.
So, in my example I used 5 NULL values to fill the first 8 argument spots, then start the values for the ...)
See full answer:
https://github.com/xamarin/xamarin-macios/issues/10285

PHP Extension return structure

I am working on a PHP extension and wants to let PHP returns a structure. But it always cause core dump. My step is:
./ext_skel --extname=test
./configure --enable-test
in php_test.h, add:
typedef struct mydata {
int m_id;
int m_age;
}MYDATA;
PHP_FUNCTION(wrap_getMydata);`
In test.c, add:
#define MY_RES_NAME "my_resource";
static int my_resource_descriptor;
PHP_FE(wrap_getMydata, NULL)
...
ZEND_MINIT_FUNCTION(test)
{
/* If you have INI entries, uncomment these lines
REGISTER_INI_ENTRIES();
*/
resid = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);
return SUCCESS;
}
PHP_FUNCTION(test_getMydata)
{
zval* res;
long int a, b;
long int result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
return;
}
MYDATA objData;
objData.m_id = a;
objData.m_age = b;
ZEND_REGISTER_RESOURCE(res, &objData, resid);
RETURN_RESOURCE(res);
}
add: var_dump(test_getMydata(3,4)) in test.php
then make; make install; ./php test.php, it prints:
Functions available in the test extension:
confirm_wrap_compiled
test_getMydata
Congratulations! You have successfully modified ext/wrap/config.m4. Module wrap is now compiled into PHP.
Segmentation fault (core dumped)
$ gdb ../../bin/php core.23310
Loaded symbols for /home/user1/php/php-5.2.17/lib/php/extensions/no-debug-non-zts-20060613/test.so
#0 0x00000000006388ad in execute (op_array=0x2a9569bd68) at /home/user1/php/php-5.2.17/Zend/zend_vm_execute.h:92
92 if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) {`
Can someone give some help?
sorry for the bad formatting in the comment - here is my final answer:
i had to rename the extension from test enter code hereto hjtest - everthing else should be pretty much in line with your posted sample.
tl;dr - the problem - and SIGSEGV in your sample is that you are registering a resource to a local variable objData - wich at the end of the function is not reachable anymore - you need to use emalloc to get a piece of dynamic memory - wich holds your MYDATA
as from there you have a resource - bound to some piece of dyn. memory, you need to register a dtor function - so you can release/efree your registered memory.
hope that helps.
to solve the above issue - modifie your resource registration like this:
MYDATA * objData=emalloc(sizeof(MYDATA));
objData->m_id = a;
objData->m_age = b;
ZEND_REGISTER_RESOURCE(return_value, objData, resid);
and add a dtor:
... MINIT
resid = zend_register_list_destructors_ex(resdtor, NULL, MY_RES_NAME, module_number);
and
static void resdtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
MYDATA *res = (MYDATA*)rsrc->ptr;
if (res) {
efree(res);
}
}
for full sample see this GIST: https://gist.github.com/hjanuschka/3ed54e66f017a379cf25

How to declare a C function with an undetermined return type?

Can I declare a C function with an undetermined return type (without C compiler warning)? The return type could be int, float, double, void *, etc.
undetermined_return_type miscellaneousFunction(undetermined_return_type inputValue);
And you can use this function in other functions to return a value (although that could be a run time error):
BOOL isHappy(int feel){
return miscellaneousFunction(feel);
};
float percentage(float sales){
return miscellaneousFunction(sales);
};
What I'm looking for:
To declare and to implement a C function (or Obj-C method) with an undefined-return-type could be useful for aspect-oriented programming.
If I could intercept Obj-C messages in another function in run time, I might return the value of that message to the original receiver or not with doing something else action. For example:
- (unknown_return_type) interceptMessage:(unknown_return_type retValOfMessage){
// I may print the value here
// No idea how to print the retValOfMessage (I mark the code with %???)
print ("The message has been intercepted, and the return value of the message is %???", retValOfMessage);
// Or do something you want (e.g. lock/unlock, database open/close, and so on).
// And you might modify the retValOfMessage before returning.
return retValOfMessage;
}
So I can intercept the original message with a little addition:
// Original Method
- (int) isHappy{
return [self calculateHowHappyNow];
}
// With Interception
- (int) isHappy{
// This would print the information on the console.
return [self interceptMessage:[self calculateHowHappyNow]];
}
You can use a void * type.
Then for example:
float percentage(float sales){
return *(float *) miscellaneousFunction(sales);
}
Be sure not to return a pointer to a object with automatic storage duration.
You may use the preprocessor.
#include <stdio.h>
#define FUNC(return_type, name, arg) \
return_type name(return_type arg) \
{ \
return miscellaneousFunction(arg); \
}
FUNC(float, undefined_return_func, arg)
int main(int argc, char *argv[])
{
printf("\n %f \n", undefined_return_func(3.14159));
return 0;
}
May be a union as suggested by thejh
typedef struct
{
enum {
INT,
FLOAT,
DOUBLE
} ret_type;
union
{
double d;
float f;
int i;
} ret_val;
} any_type;
any_type miscellaneousFunction(any_type inputValue) {/*return inputValue;*/}
any_type isHappy(any_type feel){
return miscellaneousFunction(feel);
}
any_type percentage(any_type sales){
return miscellaneousFunction(sales);
}
Here with ret_type you can know data type of return value and ret_type. i,f,d can give you corresponding value.
All elements will use same memory space and only one should be accessed.
Straight C doesn't support dynamically-typed variables (variants) since it is statically typed, but there might be some libraries that do what you want.

Declaring and using a C function in Objective C

This must be very simple, but I can't figure out how to do this: I have a C-function to monitor current memory usage:
natural_t report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
return info.resident_size;
} else {
NSLog(#"Error with task_info(): %s", mach_error_string(kerr));
return 0;
}
}
Now, I would like to use it. How do I declare it in the .h?
I tried the (for me) obvious within the objective c methods:
natural_t report_memory(void);
Calling this somewhere in the code:
NSLog(#"Memory used: %u", rvC.report_memory());
The Compiler complains error: called object is not a function. Thus, I assume, the declaration is somehow wrong. I tried several options, but the best I could get was a runtime error...
How to fix this?
rvC.report_memory()
should be replaced with
report_memory()
since it is a C function.
If you want to use this function in other modules, you should also put in your header (.h) file this line
extern natural_t report_memory(void);

function with multiple arguments

how to pass multiple arguments in a single function in Objective-C? I want to pass 2 integer values and the return value is also integer. I want to use the new Objective-C syntax, not the old C/C++ syntax.
In objective-c it is really super easy. Here is the way you would do it in C:
int functName(int arg1, int arg2)
{
// Do something crazy!
return someInt;
}
This still works in objective-c because of it's compatibility with C, but the objective-c way to do it is:
// Somewhere in your method declarations:
- (int)methodName:(int)arg1 withArg2:(int)arg2
{
// Do something crazy!
return someInt;
}
// To pass those arguments to the method in your program somewhere:
[objectWithOurMethod methodName:int1 withArg2:int2];
Best of luck!
Since this is still google-able and there are better solutions than the accepted answer; there's no need for the hideous withArg2 – just use colons:
Declaration:
#interface
-(void) setValues: (int)v1 : (int)v2;
Definition:
#implementation
-(void) setValues: (int)v1 : (int)v2 {
//do something with v1 and v2
}
Like this:
int sum(int a, int b) {
return a + b;
}
Called like this:
int result;
result = sum(3, 5);
// result is now 8
More here
int add (int a, int b)
{
int c;
c = a + b;
return c;
}
link text