I am writing the Objective-C part of a Unity project. In AppController.mm, I declared
extern void UnitySendMessage(const char *, const char *, const char *);
And I am calling this like,
- (void)callUnityObject:(const char*)object Method:(const char*)method Parameter:(const char*)parameter
{
UnitySendMessage(object, method, parameter);
}
But I have a Unity function that has to receive an int parameter.
So, if I call like this:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:"50"];
The app doesn't crash, but the call doesn't work and I am getting an output like this:
The best match for method GiveDynamite has some invalid parameter.
If I call like this:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:50];
The App is crashing.
How can I send this message from Objective-c to Unity?
I tried declaring a new method like this:
extern void UnitySendMessage(const char *, const char *, int);
But the app crashed and said that unity doesn't have a function declaration like that.
Thanks in advance.
According to:
void UnitySendMessage( const char * className, const char * methodName, const char * param )
You should pass char*:
[self callUnityObject:"_iosManager" Method:"GiveDynamite" Parameter:"50"];
On Unity class you should receive "string" param
void GiveDynamite(string dinamite) {
...
}
and then parse it to integer value, f.e:
dinamiteAmount = int.Parse(dinamite);
Related
I am using dart:ffi to call C++ functions.
I have following code in C++
typedef void* (*unmanaged_callback_ptr)(const char* , const char*);
typedef char* (*managed_direct_method_ptr)(const char*,
const char* , unmanaged_callback_ptr);
methods as follows which uses function pointer as returns type or as argument
CPPLIB_API managed_direct_method_ptr CreateManagedDelegate(const char* libName,
const char* type,
const char* methodName);
CPPLIB_API char* InvokeManagedFunction(const char* name,
const char* args,
unmanaged_callback_ptr unmanagedCallback);
Question is how do I call these methods using dart:ffi ?
I mean how to define typedefs, lookup method and fetch the result when function returning function ptr i.e. say managed_direct_method_ptr returned by CreateManagedDelegate(..)
Finally I find the solution for my problem. So following are typedefs for the C++ methods
// typefefs for method 'CreateManagedDelegate' which returns managed_direct_method_ptr
typedef get_create_d = Pointer<NativeFunction<managed_direct_method>> Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
typedef getCreateD = Pointer<NativeFunction<managed_direct_method>> Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>);
// Typedefs of managed_direct_method
typedef managed_direct_method = Pointer<Utf8> Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<NativeFunction<unmanaged_call_back>>);
typedef managedDirectMethodDart = Pointer<Utf8> Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<NativeFunction<unmanaged_call_back>>);
// These are typedefs for actual function in C++ for which function ptr is defined
typedef unmanaged_call_back = Int32 Function(Pointer<Utf8>, Pointer<Utf8>);
typedef unmanagedCallBackDart = int Function(Pointer<Utf8>, Pointer<Utf8>);
Now how to use this typedefs for calling function which returns function ptr is as follows. I have already have handle to DLL as dyLib
// Get create_d which returns managed_direct_method_ptr
getCreateD createD = dyLib
.lookup<NativeFunction<get_create_d>>('CreateManagedDelegate')
.asFunction();
..... // Assume that args to pass in method are defined as String<Utf8>
Pointer<NativeFunction<managed_direct_method>> directMethodPtr =
createD(managedLib, mType, methodName);
managedDirectMethodDart directMethod = directMethodPtr.asFunction();
// Now call the function using function ptr
Pointer<NativeFunction<unmanaged_call_back>> fptr =
bridgeLib.lookup('unmanagedCallback');
final outList = directMethod(methodName, ''.toNativeUtf8(), fptr).toDartString();
Instead of returning function pointer, one can just return a bool as status and set up function pointer inside the C++ method which can be member of class/struct.
Using this approach also you can avoid all above stuff and make it more simpler.
As this is working for me, I am marking it as 'Solved'
I'm using C++Builder 10.4.2 and having a problem with qsort. I rarely use qsort so I might be making a clumsy mistake. Array 'buffer' is a 2D 'char' array with more than 26,000 rows of single words.
This is the call:
qsort((void *)buffer,wordcount,sizeof(buffer[1]),sort_function);
This is the compare function:
int TForm::sort_function(const void *a, const void *b)
{
return( strcmp((char *)a,(char *)b) );
}
This is the error message. Notice that it's complaining about sort_function for 4th argument:
search.h(46): candidate function not viable: no known conversion from 'int (__closure *)(const void *, const void *)' to 'int (*)(const void *, const void *) __attribute__((cdecl))'
What is 'int (__closure *)'? Is there a way to fix my compare function?
__closure is a Borland compiler extension for obtaining a pointer to a non-static class method, without regard to the type of class being used. This is most commonly used in VCL/FMX components, which allow you to assign event handlers from any class you want, which is not something that standard C++ typically allows you to do.
qsort() expects a C-style function pointer in the 4th parameter. You can't get such a pointer to a non-static class method.
To solve this, you need to use either:
a standalone function
a static class method
a non-capturing C++ lambda (C++11 or higher only)
Since your sort_function() does not need access to your TForm object, declaring sort_function() as static would be the simplest fix:
// .h
class TForm
{
...
private:
static int sort_function(const void *a, const void *b);
void doSomething();
...
};
// .cpp
int TForm::sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
However, it really should be a standalone function instead since it really has no relation to your TForm class at all:
// .cpp
static int sort_function(const void *a, const void *b)
{
return strcmp((const char *)a, (const char *)b);
}
void TForm::doSomething()
{
...
qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
...
}
I am using SNMP++ library in my project and everything works fine. However, there is a method where I need to get callback in my .mm file. Now when I am creating a block and passing it to that function as parameter, it throws an error "No matching member function for call to 'get_bulk'". Here is the piece of code:
void(^callbackFunc)(int,Snmp*,Pdu&,SnmpTarget&,void*);
callbackFunc = ^(int i,Snmp* s,Pdu& p,SnmpTarget& t,void* v) {
};
snmp.get_bulk(pdu, *target, l_repeaters, l_repetitions,callbackFunc);
Also, here is the function signature for "get_bulk" function:
int Snmp::get_bulk(Pdu &pdu, // pdu to use
const SnmpTarget &target, // destination target
const int non_repeaters, // number of non repeaters
const int max_reps, // maximum number of repetitions
const snmp_callback callback,// callback to use
const void * callback_data) // callback data
{
pdu.set_type( sNMP_PDU_GETBULK_ASYNC);
return snmp_engine( pdu, non_repeaters, max_reps, target,
callback, callback_data);
}
What should I pass in 'callback' type?This is the typedef for SNMP_callback:
typedef void (*snmp_callback)(int reason, Snmp *session,
Pdu &pdu, SnmpTarget &target, void *data);
I am stuck on this for the past 4-5 hours now and I can't figure out how to resolve this.
Apple's blocks are not convertible to function pointers, as they also contain data (captured variables, etc.) and a reference counting mechanism. You will need to pass a free function, static C++ class member function, or a C++ non-capturing lambda as the callback.
The lambda is the closest syntactically to a block; only non-capturing lambdas are convertible to a function pointer, however, so you will need to do the capturing "by hand" by passing a pointer to a context struct or similar through the void* callback_data argument which presumably is passed through to the callback as void* data.
The lambda will look something like this:
snmp_callback callback =
[](int reason, Snmp *session, Pdu &pdu, SnmpTarget &target, void *data)
{
// context_struct_type* context = static_cast<context_struct_type*>(data);
};
I was trying to send some data using UnitySendMessage in iOS plugin, but it seem like it doesn't do anything, i don't see any errors and response. I checked function where UnitySendMessage is located, and i'm 100% sure that it starts.
- (void) callback{
NSLog(#"UNITY test callback");
UnitySendMessage("PluginTest", "listener", "test callback");
}
On scene i have gameObject named PluginTest with pluginListener component which contains method:
public void listener(string parameter)
{
print(parameter);
}
I also added to UnityAppController.mm this line, which was recommended to add in some post:
extern void UnitySendMessage(const char *, const char *, const char *);
I have no idea what i'm doing wrong, unitySendMessage seems like it should work without much effort.
Any help will be appreciated
We know that we call pthread like this:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
Hi guys, i want to know why the return type of third parameter is void*? why not void?
Because there is no way for a start function to know what kind of data a developer wants to return from the function they use a void* that can point to any type. It is up to the developer of the start function to then cast the void* to appropriate type he actually returned before using whatever the void* points to. So now the start function can return a pointer that may in actually point to anything. If the start function is declared to return void, it means this function returns nothing, then what if the developer wants the start function to return a int, a struct? For example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
struct test {
char str[32];
int x;
};
void *func(void*) {
struct test *eg = (struct test *)malloc(sizeof(struct test));
strcpy(eg->str,"hello world");
eg->x = 42;
pthread_exit(eg);
}
int main (void) {
pthread_t id;
struct test *resp;
pthread_create(&id, NULL, func, NULL);
pthread_join(id,(void**)&resp);
printf("%s %d\n",resp->str,resp->x);
free(resp);
return 0;
}
More details on this post: What does void* mean and how to use it?