Overloading function in C++ as unsigned char and unsigned int result in ambiguous - g++

I have to overloaded functions:
void wypisz(unsigned int32 x, int n = 1);
void wypisz(unsigned char x, int n = 1);
here is code where I rise them:
main()
{
wypisz((int32)(32), 7);
wypisz('a', 7);
return 0;
}
and when I try to compile it using G++ I get an error:
test.cpp: In function 'int main()':
test.cpp:10:21: error: call of overloaded 'wypisz(int, int)' is
ambiguous wypisz((int)(32), 7);
test.cpp:10:21: note: candidates are:
test.cpp:5:6: note: void wypisz(unsigned int, int) void wypisz(unsigned int x, int n = 1);
test.cpp:6:6: note: void wypisz(unsigned char, int) void wypisz(unsigned char x, int n = 1);
When I remove unsigned it will compile fine.
Is there a way to call this method - wha tI should change in the call statement? Unfortunatelly I can not change anything in the declaration = they must stay as they are.

The problem is that, in your function call, you are casting to an int32, which is neither an unsigned char nor an unsigned int32. In fact, it is implicitly castable to either of them (the compiler can convert it automatically). However, because it can convert it to either automatically, it doesn't know which to convert it to, and that is why the call is ambiguous.
To call the method unambiguously, just cast it to an unsigned int32:
wypisz((unsigned int32)32, 7);
Now, the compiler doesn't have to do any implicit casting, since there is an exact match. Instead, it just calls the right function.

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

c and objective-c -- const char* and char*

I have a function:
-(void)ADPCMDecode:(char *)indata : (short *)outdata :(long)len {
indata is a char and the function does pointer arithmetic to iterate for a length of len, modifying outdata, which is a short and I will need to do pointer arithmetic to get the values from it.
I am attempting to call the function using:
const char *modulatedBytes1 = [modulatedAudio bytes];
char *modulatedBytes [] = modulatedBytes1;
unsigned int moduleatedLength = [modulatedAudio length];
short *decompressedBytes = NULL;
[self ADPCMDecode:modulatedBytes :decompressedBytes :moduleatedLength];
DLog(#"%hi",decompressedBytes[1]);
I get a BAD ACCESS error on this line: *outp++ = valprev; within the function, because I am passing a constant char * instead of a char *
How should I call the function, and how would I get the output from it?
I have no background in C, which is why I do not understand how to go about doing this.
Here is the C only version of the same question:
https://pastee.org/d3y3z

pointer to function syntax and usage

I apologize if this was asked many times.
I'm trying to understand why both of this works fine without any warnings or other visible issues (in Xcode):
int testFunctionAcceptingIntPointer(int * p) {
return *p = *p +5;
}
void test() {
int testY = 7;
typedef int (*MyPointerToFunction)(int*);
// Both this (simply a function name):
MyPointerToFunction functionPointer = testFunctionAcceptingIntPointer;
// And this works (pointer to function):
MyPointerToFunction functionPointer = &testFunctionAcceptingIntPointer;
int y = functionPointer(&testY);
}
The code works fine without warnings both ways because a function designator is converted to a function pointer
MyPointerToFunction functionPointer = testFunctionAcceptingIntPointer;
unless it is the operand of the address operator
MyPointerToFunction functionPointer = &testFunctionAcceptingIntPointer;
(or sizeof and _Alignof).
In the first assignment, you don't use &, so the automatic conversion is done, resulting in a function pointer of appropriate type, in the second, you explicitly take the address, resulting in a function pointer of the appropriate type.

How to fix error Format specifies type 'char *' but the argument has type 'char'

I get a warning saying:
"Format specifies type 'char *' but the argument has type 'char'" for the student variable. I am copying/pasting the code out of a book into xcode and am not sure how to fix this. The only thing that prints in the console is "(lldb)". Any advice
#include <stdio.h>
void congratulateStudent(char student, char course, int numDays)
{
printf("%s has done as much %s Programming as I could fit into %d days.\n", student, course, numDays);
}
int main(int argc, const char * argv[])
{
// insert code here...
congratulateStudent("mark", "Cocoa", 5);
return 0;
}
void congratulateStudent(char *student, char *course, int numDays)
the %s means that you are going to print a string ( array of chars)
and char student this means that student is a char type
so student here is not a pointer to a string
In order to change the student type from char to a string pointer you have to add asterisk to student char *student
In your code you are calling the congratulateStudent with input parameter string "mark". So to support this string the input parameter student should be defined as pointer of string
so you are missing the asterisk in the definition of student
The same thing for course
void congratulateStudent(char *student, char *course, int numDays)
Use Function signature like because you are passing string as argument to function in main but function has character type argument..

How do I get the int value from object_getIvar(self, myIntVar) as it returns a pointer

if the variable in object_getIvar is a basic data type (eg. float, int, bool) how do I get the value as the function returns a pointer (id) according to the documentation. I've tried casting to an int, int* but when I try to get that to NSLog, I get error about an incompatible pointer type.
Getting:
myFloat = 2.34f;
float myFloatValue;
object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue);
NSLog(#"%f", myFloatValue);
Outputs:
2.340000
Setting:
float newValue = 2.34f;
unsigned int addr = (unsigned int)&newValue;
object_setInstanceVariable(self, "myFloat", *(float**)addr);
NSLog(#"%f", myFloat);
Outputs:
2.340000
For ARC:
Inspired by this answer: object_getIvar fails to read the value of BOOL iVar.
You have to cast function call for object_getIvar to get basic-type ivars.
typedef int (*XYIntGetVariableFunction)(id object, const char* variableName);
XYIntGetVariableFunction intVariableFunction = (XYIntGetVariableFunction)object_getIvar;
int result = intVariableFunction(object, intVarName);
I have made a small useful macro for fast definition of such function pointers:
#define GET_IVAR_OF_TYPE_DEFININTION(type, capitalized_type) \
typedef type (*XY ## capitalized_type ## GetVariableFunctionType)(id object, Ivar ivar); \
XY ## capitalized_type ## GetVariableFunctionType XY ## capitalized_type ## GetVariableFunction = (XY ## capitalized_type ## GetVariableFunctionType)object_getIvar;
Then, for basic types you need to specify calls to macro (params e.g. (long long, LongLong) will fit):
GET_IVAR_OF_TYPE_DEFININTION(int, Int)
And after that a function for receiving int(or specified) variable type become available:
int result = XYIntGetVariableFunction(object, variableName)
The value that is returned is the value from the right place in the object; just not the right type. For int and BOOL (but not float), you could just cast the pointer to an int or BOOL, since pointers and ints are the same size and they can be cast to each other:
(int)object_getIvar(obj, myIntVar)
It's probably boxing the value in an NSNumber. You can verify this by NSLogging the returned id's className, like so:
id returnedValue = object_getIvar(self, myIntVar);
NSLog(#"Class: %#", [returnedValue className]);
Edit: I found another question just like this one here: Handling the return value of object_getIvar(id object, Ivar ivar)
From my own experimentation, it would appear that my original assumption was incorrect. int and float and other primitives appear to be returned as the actual value. However, it would be appropriate to use ivar_getTypeEncoding to verify that the returned value is the type that you're expecting it to be.
you can use object_getInstanceVariable directly: (haven't tested it)
void *ptr_to_result;
object_getInstanceVariable(obj, "intvarname", &ptr_to_result);
float result = *(float *)ptr_to_result;