Does this function IOHIDManagerRegisterDeviceMatchingCallback operate under the cocoa environment? - c

I am struggling to implement an HID control with a Mac : I cannot send the expected function as depicted here below:
IOHIDManagerRegisterDeviceMatchingCallback( gIOHIDManagerRef, Handle_DeviceMatchingCallback, NULL );
with : gIOHIDManagerRef -> the valid HID manager dedicated to this routine
Handle_DeviceMatchingCallback --> the routine that will be called back when the HID
device is attached to the USB port
NUUL --> not used here, contain data from the USB
The issue is that Handle_DeviceMatchingCallback must be a pointer to the routine, but how can I send a pointer ?
On the other hand, all the examples , from the Apple source, are based on C, not on cocoa.
Well, does that means that I must rework my program in C ??? Or is it possible to have fraction of the program in C under the cocoa environment?
Sorry for so "stupid" question queries, but, although I have some background in the field of electronic an programming, I am very newbees with cocoa.
Your comments will be very appreciated !
Michael

Objective-C is mostly a super-set of C. In order to combine C and Objective-C code, you simply compile your C code as if it were Objective-C code. The easiest way to do this in Xcode is to ensure the file in question has a .m extension.
To route handling back to the Objective-C world, you need a pointer to an Obj-C object. Many callback-based APIs allow you to provide a generic pointer (void *) that they then pass back to you when they callback. This argument has several common names:
context or ctx
refcon (for "reference constant")
userData
userInfo
If the callback API does not allow this, you'll need some uglier way to dispatch the callback to your object, such as a global pointer or a lookup table.
The API you're using does let you provide a context pointer. When it calls back to your code, it provides you with the pointer you used when you registered for the callback. Here is an example of registering the callback from an object of type MyObjCClass (see the -registerMatching method below) and then using the context pointer to route the callback back to the object that registered the callback for handling (see the Handle_DeviceMatchingCallback function's use of the context pointer).
/*! #file C-ObjC-Callbacks.m
* Demonstrates routing a C callback to an Obj-C object
* using the callback's context pointer.
*/
#import <Cocoa/Cocoa.h>
#import <IOKit/hid/IOHIDManager.h>
// Global HID manager reference.
IOHIDManagerRef gIOHIDManager;
// HID callback
void Handle_DeviceMatchingCallback(void *context,
IOReturn result,
void *sender,
IOHIDDeviceRef device);
#interface MyObjCClass : NSObject {
}
- (void)registerMatching;
- (void)handleMatchingDevice:(IOHIDDeviceRef)device
sender:(void *)sender
result:(IOReturn)result;
#end
#implementation MyObjCClass
- (void)registerMatching {
// Assume gIOHIDManager has already been created.
// Set up a device matching callback, providing a pointer to |self| as the context.
IOHIDManagerRegisterDeviceMatchingCallback(gIOHIDManager,
Handle_DeviceMatchingCallback,
(void *)self);
}
- (void)handleMatchingDevice:(IOHIDDeviceRef)device
sender:(void *)sender
result:(IOReturn)result {
// Do something...
}
#end
void
Handle_DeviceMatchingCallback(void *context,
IOReturn result,
void *sender,
IOHIDDeviceRef device); {
MyObjCClass *const myObject = (MyObjCClass *const)context;
[myObject handleMatchingDevice:device sender:sender result:result];
}

Handle_DeviceMatchingCallback must be a pointer to the routine, but how
can I send a pointer ?
If you want to pass in a function functionName, you can pass it as
&functionName.
On the other hand, all the examples , from the Apple source, are based on
C, not on cocoa. Well, does that means that I must rework my program in C
??? Or is it possible to have fraction of the program in C under the cocoa
environment?
You can mix C and Objective-C at will. As long as you pass it a function,
and not a method attached to an object, it should work.

Related

Can we use C struct based API directly from Swift?

I walked away from WWDC 2016 with the understanding that we should be wary about using C-based struct API directly from Swift. In Concurrent Programming With GCD in Swift 3, talking about C-based locks, they were very specific:
... And in Swift, since you have the entire Darwin module at your disposition, you will actually see the struct based traditional C locks. However, Swift assumes that anything that is struct can be moved, and that doesn't work with a mutex or with a lock. So we really discourage you from using these kind of locks from Swift. ...
... And if you want something ... that looks like the locks that you have in C, then you have to call into Objective-C and introduce a base class in Objective-C that has your lock as an ivar.
And then you will expose lock and unlock methods, and a tryLock if you need it as well, that you will be able to call from Swift when you will subclass this class. ...
#implementation LockableObject {
os_unfair_lock _lock;
}
- (void)lock { os_unfair_lock_lock(&_lock); }
- (void)unlock { os_unfair_lock_unlock(&_lock); }
#end
However, watching WWDC 2019 Developing a Great Profiling Experience, I notice that the author is using os_unfair_lock directly from Swift, without this Objective-C wrapper, effectively:
private var workItemsLock = os_unfair_lock()
func subWorkItem(...) {
...
os_unfair_lock_lock(&self.workItemsLock)
...
os_unfair_lock_unlock(&self.workItemsLock)
...
}
Empirically, this sort of direct use of os_unfair_lock appears to work, but that doesn’t mean anything. Respecting the caveat in the 2016 WWDC video, I have refrained from using os_unfair_lock directly from Swift.
So, the question is, are they being (ever so slightly) sloppy in the use of this API in this 2019 sample? Or was the 2016 video incorrect in its claims? Or has the handling of C-based struct changed since Swift 3, now rendering this pattern safe?
The API example of using private var workItemsLock = os_unfair_lock() can fail at runtime.
The threading primitives from C need a stable memory location so to use them or another struct that has one of these primitives directly as a member of it you have to use UnsafePointer. The reason for this is that UnsafePointer APIs once they have allocated a chunk of memory that memory is stable and cannot be moved or trivially be copied by the compiler.
If you change the example like this it is now valid
private var workItemsLock: UnsafeMutablePointer<os_unfair_lock> = {
// Note, somewhere else this will need to be deallocated
var pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
pointer.initialize(to: os_unfair_lock())
return pointer
}()
func subWorkItem(...) {
...
os_unfair_lock_lock(self.workItemsLock)
...
os_unfair_lock_unlock(self.workItemsLock)
...
}

Swift can't call self from c callback in linphone sdk

I have problem when try to call Swift instance method from c callback.
Error: "A C function pointer cannot be formed from a closure that captures context."
linphone_core_cbs_set_registration_state_changed(cbs) { (lc, cfg, state, message) in
switch state{
case LinphoneRegistrationOk:
print("LinphoneRegistrationOk")
self.call()
}
func call() {
let account = "test"
let domain = "sip.linphone.org"
let identity = "sip:" + account + "#" + domain
linphone_core_invite(lc, identity)
}
If you have the ability to pass an arbitrary void* as a context then using Unmanaged<SelfType>.passUnretained(self).toOpaque() and converting it back with Unmanaged<SelfType>.fromOpaque(context).takeUnretainedValue() is the best solution.
But based on your small snippet of (lc, cfg, state, message) none of them seem like a context pointer. So getting self back is still possible but likely more complex. Because you will need to create a global/static piece of data that can be accessed from inside your closure in a safe manner. Some ideas of how you can do this are below:
1) You can do this with just a simple global/static if you know that is safe.
2) You can use thread local storage and store a pointer to self and cast it back and forth in the same way as if you had the void* argument and used Unmanaged. This one of course requires that your C callback be raised on the same thread where you store the value.
3) If you have access to a unique identifier that both Swift and C can access that will continue to be valid and accessible in your callback you can create a map of type [UniqueIdentifierAccessibleBySwiftAndC: TypeOfSelf] and use that to get self back.

Create Direct3DEx interface from C doesn't work

i have to admit that i have really strange issue, which im not able to solve by my self. Im trying from few days without success.
My goal is to use Direct3DEx interfaces from C (not C++). I cant use Direct3D because i have to deal with shared resource handles with surfaces from different d3ddevices.
I have no any problems with creating IDirect3DEx from C++, works perfectly. For example this code works as expected
IDirect3D9Ex* m_d3d;
Direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d);
UINT c = m_d3d->GetAdapterCount();
m_d3d->Release();
Now im trying to do exactly the same from C,
my code is:
void *pd3dll = (void *) LoadLibrary("d3d9.dll");
UINT count;
IDirect3D9Ex *pDirect3D9ExInterface;
HRESULT hr;
typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
Direct3DCreate9Ex_t Direct3DCreate9ExFunc;
Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t) GetProcAddress((HMODULE) pd3dll, "Direct3DCreate9Ex");
hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
if (SUCCEEDED(hr))
{
count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash
IDirect3D9Ex_Release(pDirect3D9ExInterface);
}
i dont see absolutly any reason why this piece of code doesnt work.
Please notice that code line:
hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
returns S_OK, and when im checking pDirect3D9ExInterface pointer under debuger it looks like a valid pointer.
But this line of code:
count = IDirect3D9Ex_GetAdapterCount(pDirect3D9ExInterface); //crash
causes my program to crash. When im switching my DirectX9 to debug mode, on VS output window i see after crash, something like this:
Direct3D9: (ERROR) :Invalid initialization function specified. RegisterSoftwareDevice fails.
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Additionaly if i change this C code to Direct3D initialization (no Direct3DEx) than works without any problems.
What im doing wrong? Where is the catch?
thanks in advance
Jakub
This seems to be due to a bug in the definition of the d3d9.h header file.
A function seems to be left out of the IDirect3D9Ex interface that appears in the IDirect3D9 interface (IDirect3D9Ex inherits from IDirect3D9).
In c++ this still works because of inheritance and virtual functions working correctly, in c, it doesn't correctly pick up the inheritance due to the way their v-tables are constructed.
Below I've commented out the line that needs to be added to fix this issue (in d3d9.h at line 2044):
DECLARE_INTERFACE_(IDirect3D9Ex, IDirect3D9)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IDirect3D9 methods ***/
//Add this here: STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;
STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
You can double check that the functions line up correctly with the returned interface by loading the d3d9.dll symbols from the MS servers and comparing the names in the v-table with the values reported. In the image below, the left hand side is the v-table before being fixed, and the right hand side is the v-table after being fixed.
To get the symbol's from the MS symbol servers:
start the application and place a breakpoint after LoadLibrary("d3d9.dll") has been called
open up the 'Modules' window (from the menu bar Debug->Windows->Modules)
Find d3d9.dll in the modules list (try typing d3d9.dll to quickly go to it)
Right-click on d3d9.dll and click on Load Symbols From->Microsoft Symbol Servers
Wait a few seconds for it to download and load the symbols, addresses should then resolve to useful names.

D-Bus how to create and send a Dict?

I have a process which exposes a method to DBus with one of the arguments taking the following type signature a{sv}:
Dict of {String, Variant}
The libDBus documentation for dbus_message_append_args fails to provide adequate reference for this. Some information appears in the specification under container-types, specifically:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
On attempting to append a dict I receive the following error message:
type dict_entry isn't supported yet in dbus_message_append_args_valist
Although I'm actually using dbus_message_append_args(I guess the error message is somewhat off).
There are two other alternatives to dbus_message_append_args() using either:
dbus_message_iter_append_basic()
and
dbus_message_iter_append_fixed_array()
While I can create an empty Dict container with the following:
const char * container_d_sig = "{sv}";
DBusMessageIter iter, sub;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
dbus_message_iter_close_container(&iter, &sub);
Neither of the append methods appear to support adding a struct. Not sure what to try here...
First, about D-Bus libraries: you talk about dbus-glib in several places but the functions you refer to are not part of dbus-glib but libdbus. If you are still trying to find the best way to use D-Bus, I suggest you forget both of these: libdbus is very low-level (it's documentation even starts with "If you use this low-level API directly, you're signing up for some pain") and dbus-glib is deprecated. The best D-Bus API currently is GDBus which is part of GLib GIO: it's a far better designed API than either of the other two, well tested and supported.
Now, as for the actual question, documentation for dbus_message_append_args() does say it quite clearly:
To append variable-length basic types, or any more complex value, you
have to use an iterator rather than this function.
In other words you should use dbus_message_iter_open_container() to prepare the iterator until it is pointing to somewhere where you can use dbus_message_iter_append_basic(). Note that in your example the dictionary is a container, the dictionary entry is a container and the variant is a container... In other words it gets pretty complex quite fast. If you really want to do it, look at e.g. Connman code for examples.
As I mentioned, the sane route is GDBus. There creating even much more complex signatures is pretty easy as you can use the GVariantBuilder API:
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
/* Now use the builder results with g_dbus_connection_call()
or g_dbus_proxy_call() */
I know this question was asked awhile ago, but I had a very similar question recently, and after several hours of trial and error this is some code I came up with that works for me. Hopefully it helps someone else...
DBusMessage* testMessage()
{
DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
DBusMessageIter iter, aIter;
dbus_message_iter_init_append(mssg, &iter);
if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
return nullptr;
DBusMessageIter eIter;
if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
const char* key = "test key";
dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
DBusMessageIter vIter;
if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
dbus_int32_t val = 42;
dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
dbus_message_iter_close_container(&eIter, &vIter);
dbus_message_iter_close_container(&aIter, &eIter);
dbus_message_iter_close_container(&iter, &aIter);
return mssg;
}
This is C++ but should be pretty easy to adapt for C. The returned message has a signature of a{sv}. The dbus docs are helpful-ish.

Gtk signal with multiple arguments

Context
After writing a simple application using a GtkEntry widget to process textual commands from user I would like to do some design changes.
As of now I use signal hook on key-press. If key(s) are a specified value, then show command line and process various actions on entry widget. Like e.g.
Ctrl+a: move cursor to start of input.
Ctrl+u: delete text before the cursor.
...
As well as parsing commands and saving/loading history.
I am not satisfied with how this is stitched together. The command parsing becomes a subset of:
main_window -> mode_check -> command_line_act -> parse_cmd+execute
As I see it one good approach would be to write a new widget using GtkEntry as base – and send signals on command enter. All of the internals like Ctrl+... and history handled by the new widget.
Signals emitted from new widget being e.g.:
"cmdline-abort"
"cmdline-cmd"
...
Status
Have written the base for this but I am at a hault when it comes to emitting signals with more then one argument.
I have:
gtk_signal_emit(obj, sig, 0, command)
|
+---- string.
but would like, (for now at least, most likely more/other down the line.):
gtk_signal_emit(obj, sig, 0, command, length)
gtk_emit_signal Typo fixed. Thanks to jku.. Also, now using g_signal_
In widget code:
static void
cmdline_class_init(CmdlineClass *klass)
{
With one argument I am using g_signal_new() as:
cmdline_signals[CMDLINE_CMD] = g_signal_new(
"cmdline-cmd",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET(CmdlineClass, cmdline),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
1,
G_TYPE_STRING
);
And as I see it, for two arguments, should change it to something like:
cmdline_signals[CMDLINE_CMD] = g_signal_new(
"cmdline-cmd",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET(CmdlineClass, cmdline),
NULL,
NULL,
g_cclosure_user_marshal_VOID__STRING_INT,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_INT
);
Trouble in the garden
Using glib-genmarshal to generate marshals with marshal.list holding:
VOID:STRING,INT
This works, but gives me a warning upon compile time as:
warning: ISO C forbids conversion of object pointer to function pointer type
Caused by this code generated by glib-genmarshal:
typedef void (*GMarshalFunc_VOID__STRING_INT) (gpointer data1,
gpointer arg_1,
gint arg_2,
gpointer data2);
register GMarshalFunc_VOID__STRING_INT callback;
/* GCC Warnig: conversion of object pointer to function => */
callback = (GMarshalFunc_VOID__STRING_INT) (
marshal_data ?
marshal_data :
cc->callback
);
Question
Is this the wrong approach? Is there some way to fix the conversion error? Etc.
As a note: I am fairly new to Gtk, and Gui programming in general.
Side point
There are some deprecations I also wonder if could affect the code / should be avoided:
GtkSignalMarshaller, does this indicate anything about the status of GSignalCMarshaller?
GtkCallbackMarshal, does this indicate anything about the use of marshalers in general?
This warning does appear (with -pedantic) on some signal marshalling code, and not just in your code. As far as I can see you are not doing anything wrong though -- except for using gtk_signal_emit() (I assume you meant that and not gtk_emit_signal() which does not exist as far as I know): you should not use any gtk_signal-prefixed code: that stuff is all deprecated. See the reference for details. Use GObject instead: g_signal_emit() or g_signal_emit_by_name() should work for you.
The signal marshaller deprecations you mention are about this same thing: GObject handles everything related to this now (and has for a long time already).
As practical advice: Often adding things to signal signatures is not worth the trouble, and this might be the case for you as well: maybe your signal does not need the command string at all, and the signal handler could just query it with your_object_get_command()?
Practical advice #2: Consider using GTK+ 3 for new code. Not having all that deprecated stuff around confusing everyone is just lovely.

Resources