In that case, I'd see if I could avoid having any Objective-C in the backend at all. If you do, that means some platform specific stuff is creeping in to what is supposed to be the cross-platform layer.
You'll what to structure it so that primarily the GUI, platform-specific layer (Obj-C on Mac, C++ on linux, C? on Windows) makes calls to the cross-platform C layer but not the other way around.
If/when you do need callbacks from the platform neutral layer to the platform specific layer, it makes sense to consider using C functions and data types for that interface.
If your project is large, consider three layers:
1. GUI - platform specific language
2. PAL - "platform abstraction layer" You'll have one version of this for each platform
3. Cross-platform backend.
The PAL sits between the two other layers. It's only job is to make the connection between layer's 1 and 3. Each version presents the same logical interface to each of the GUI platforms it supports, but each implementation would contain language/platform specific details. It's important that the interface for the GUI-layer be logically identical across platforms even though it is implemented in the platform-specific language. For example, if a function took a rectangle parameter, it might be a CGRect on Mac and a RECT structure on Windows, but it's still representing the same thing. If you don't maintain a logically identical interface for the PAL, it loses its purpose and advantages. If the cross-platform layer does need to make callbacks to the GUI layer, the PAL would also expose an interface for that.
So calls from the GUI to the backend go through the PAL.
Mac: Layer 1 makes Objective-C call to the PAL. The PAL, in turn, makes a C call to the backend, transforming parameters, objects, etc, as needed. Return values are bundled back up a an Objective-C type, if needed.
Linux: Layer 1 makes C++ call to the PAL. The PAL transforms the parameters as needed and makes the same C call to the backend. Return values are bundled back up as a C++ type, if needed.
Win: Layer 1 makes a C# (for example) call to the PAL. The PAL transforms the parameters as needed (probably needs a lot coming from managed C# to unmanaged C) and makes the call to the PAL. Return values are bundled back up as a C# type, as needed.