Xcode: Impossible to use c++ with Scenekit? - c++

I'm a beginner with Xcode...
I'm trying to use openCV c++ with Scenekit=> to make an AR scene.
Well, I was too optimistic.
1/I started to use the default XCode template for game.=> works!
2/openCV without scenekit=> works
3/ mixing...
I imported some c++ headers in the gameviewController file (basically a UIViewController with scenekit inside).
If I let it so, I get compiler error (cstddef not defined). Fair enough, it's C++ so, from what I read, I just have to rename .m to .mm
But, in this case, I get a full list of linker errors such as Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_SCNAction", referenced from:
=> I guess it is more tricky to mix objective C and C++ but on a simpler project, without Scenekit but with a very similar code otherwise, it worked nicely.
Any clue or guide for mixing them? Should I use swift?
Thanks a lot,
Michael

I just need to add "SceneKit.framework" to Link Binary With Libraries:

Same problem here. I had a pure Objective-C class, simply named "GameViewController.m". To turn it into an Obj-C++ class, change the ".m" to ".mm".
However, just by changing the extension, the linker spat back 13 undefined symbols....
"_OBJC_CLASS_$_SCNTransaction", referenced from: ...
"_OBJC_CLASS_$_SCNFloor", referenced from: ...
"_OBJC_CLASS_$_SCNMaterial", referenced from: ...
etc...
To get around this, just create a different (new) Obj-C++ class, with a .mm extension, and place your C++ code in that class.
Now you can instantiate that new class from the class containing SceneKit calls and call the methods in the new Obj-C++ class.
Inside the GameViewcontroller.m class:
...
scene = [SCNScene sceneNamed:#"art.scnassets/grid.dae"];
kinematics = [[KinematicScene alloc] init];
[kinematics setupCharacters];
...
And inside the new Obj-C++ class (KinematicsScene.mm)
#implementation KinematicScene
{
AI::Location *location;
}
-(id) init
{
self = [super init];
if( self )
{
AI::KinematicSeek* seek = new AI::KinematicSeek[2];
location = new AI::Location[2];
}
return self;
}
-(void) setupCharacters
{
.....
}
... etc ....
#end

This worked for me:
Disable module support [CLANG_ENABLE_MODULES, -fmodules]. This has user experience downsides. Read the online help for this setting before disabling it, and also be aware that if you disable it you will become responsible for hunting down the libraries and frameworks you need to link against, and this can be tedious if you are not an old hand.
Build and (attempt to) link. Add the frameworks and libraries you need to resolve the link errors. I recommend creating a group in your project and directing it to your SDK, then adding the frameworks and libraries relative to that SDK.

Related

iOS biometrics, how to create LAContext instance from C++?

I'm trying to implement biometric authentication on iOS from a C++ codebase. Here is one example.
In order to achieve this, I need to use the LAContext obj-c APIs. However, when I try to initialize the class from C++ I get a pointer/reference error:
// Cannot initialize a variable of type 'LAContext *__strong' with an rvalue of type 'LAContext'
LAContext* authContext = LAContext();
Is there any way to achieve this? Or is this struct available from Obj-c only?
Edit 1:
My file is in Obj-C++, so in theory I should be able to mix C++ and Obj-C code, however when I try to write a Obj-C function to alloc the LAContext object I get a missing symbols error:
-(bool)biometricsAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
return true;
}
On the compilation step this error is thrown:
Undefined symbol: _OBJC_CLASS_$_LAContext
XCode itself does not show any error while editing the file, only happens when I try to build/compile the app.
As it turns out, the problem was not with mixing C++ and Obj-C code, but rather with my library being linked via cocoapods and the LocalAuthentication framework being missing.
I needed to add:
s.frameworks = "LocalAuthentication"
to the podspec and creating a LAContext instance works just fine.

Call a method or function from Objective-c in AppleScript

I'm trying to use LestMove to be more precise
the second implementation method where it says:
Option 2:
Copy the following files into your project:
PFMoveApplication.h
PFMoveApplication.m
If your project has ARC enabled, you'll want to disable ARC on the above files. You can do so by adding -fno-objc-arc compiler flag to your PFMoveApplication.m source file. See How can I disable ARC for a single file in a project?
If your application is localized, also copy the 'MoveApplication.string' files into your project.
Link your application against Security.framework.
In your app delegate's "-[applicationWillFinishLaunching:]" method, call the PFMoveToApplicationsFolderIfNecessary function at the very top.
but I'm not able to call the method / Class, could someone help me with this issue? Thanks in advance!
In general, there are a couple of ways to set up an Objective-C class in your AppleScriptObjC project:
Add the file(s) to the project - the Objective-C class name will be
the one used in the #interface/#implementation declarations
Add an outlet property in the AppleScript class/script you are using, e.g. property someProperty : missing value
Instantiate the class programmatically:
set someProperty to current application's ClassName's alloc's init()
or
Connect stuff up with the Interface Builder:
Add an NSObject (blue cube) from the library to your project
Set the class of the object/cube to the class name of the Objective-C file(s) in the Identity Inspector
Connect the AppDelegate IB Outlet to the object/cube in the Connections Inspector
After setting up the outlet property, the Objective-C methods can be used like any other script/class:
someProperty's handler()
That LetsMove project wasn't really set up for AppleScriptObjC, but I was able to tweak it a bit to get it running. I'm not that great at writing Objective-C, but the following worked for me using a new default AppleScript project with Xcode 10 in Mojave (the original file is over 500 lines long, so I'm just highlighting the changes):
Add PFMoveApplication.h and PFMoveApplication.m files to the project (the class name is LetsMove)
Add Security.framework to Link Binary With Libraries in Build Phases
As described in the original project README, add the compiler flag -fno-objc-arc to the Objective-C file in Compile Sources of the Build Phases
-- Now to alter the Objective-C files a bit:
Move the #interface declaration to the .h file and include the redefined method signatures below in it:
The PFMoveToApplicationsFolderIfNecessary and PFMoveIsInProgress methods are redefined as instance methods:
- (void)PFMoveToApplicationsFolderIfNecessary;
- (BOOL)PFMoveIsInProgress;
Redefine the above method signatures in the .m file, and include those methods in the #implementation section - to do this, move the #end to just before the helper methods (after the PFMoveIsInProgress method)
Remove the isMainThread statement at the beginning of the PFMoveToApplicationsFolderIfNecessary method - this is not not needed (AppleScript normally runs on the main thread), and fixes another issue
There is still a little stuff in there from the original app such as NSUserDefaults, so for your own project, give it a look to see if anything else needs changing (dialog text, etc)
And finally, in the AppDelegate.applescipt file, the following was added to applicationWillFinishLaunching:
current application's LetsMove's alloc's init()'s PFMoveToApplicationsFolderIfNecessary()

(iOS) How can I get the UIViewController from a C++ Application?

I need to use a library in my C++ project that needs to call an extern function:
SetGameViewController(UIViewController* gameViewController)
I have zero knowledge of Objective C and iOS yet. I need to get UIViewController and pass it to that function.
So this code should get the UIViewController:
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIViewController *rootViewController = window.rootViewController;
I also added this import:
#if defined(OS_IPHONE)
#import <UIKit/UIKit.h>
#endif
I get compiler errors like:
Expected unqualified-id
Unknown type name 'NSString'
I've started learning Objective C and read a few articles but couldn't get much further than that yet.
So basically my question is how do I basically import and use Objective C code in C++ code so that I can get and use the UIViewController?
Easiest way will be to rename your source file with the extension ".mm" - it will then be compiled as objective-c++, which means you get all the wonders of c++ while still being able to interact with objective-c objects (counted pointers to things 'derived' from NSObject).

Use "sp" in Android NDK

I'm trying to intercept some native library-calls via LD_PRELOAD.
This is working fine for simple libraries written in C, but now I try to go further and override some more complex class-methods from the AOSP written in C++.
Here's my example:
#include <rs/cpp/util/RefBase.h>
namespace android {
sp<MediaCodec> MediaCodec::CreateByType(const sp<ALooper> &looper, const char *mime, bool encoder) {
// TODO this will be implemented by me
return NULL;
}
}
In my Application.mk, I got the following piece of code:
APP_STL := gnustl_static
and inside the Android.mk this one:
LOCAL_STATIC_LIBRARIES += libstlport_static
Sadly, the error I get is the following:
jni/libhook/ld_preload.cpp:88:1: error: 'sp' does not name a type
Anyone an idea how to use sp<..> here? I assume it's not Android-specific but a standard C++-thing - I'm totally new at C++, just started "today" :)
I know this may be bad practice, so I'm welcome for any other idea.
sp<> is Android-specific. sp<> is Strong Pointer, wp<> is Weak Pointer; they came into being as part of the Binder IPC implementation.
The place to start looking for the implementation is the framework RefBase.h, which is a bit twisty for a C++ newcomer. None of what you're fiddling with is part of the public API defined by the NDK, which means it's subject to change between releases, so be aware that what you're trying to do may not work across devices or software updates.

Include Alien in portable app, C++

Ok, I've searched quite a bit, but seem unable to find an answer or example for how to achieve this.
Basically, I have an app that is designed to be portable (built using VC++ in VS2010, but no MFC or managed components, raw WinAPI). I have Lua 5.2 built into it and allow the user to write scripts inside the application. I have multiple glued functions which are exposed to the Lua scripts which handle various WinAPI calls.
However, what I'd like to be able to do is allow the user to write a script in which looks something like this:
require[[Alien/alien]]
local mb = alien.User32.MessageBoxA
mb:types{ 'long', 'long', 'string', 'string', 'long' }
print(mb(0, "Hello World!", "Test", 64))
I simply cannot seem to find a way to do this. I do not want to require the user to install Lua for Windows and, ideally, there be no core.dll and struct.dll from alien; when I tried to do something with those DLLs in ./alien/, it was crashing in Lua5.1.dll because I had LuaForWindows installed, I uninstalled LFW, and then it just states that Lua5.1.dll is missing. I have Lua 5.2 built into my app, so obviously the core/struct DLLs from the Alien rock are expecting Lua5.1.dll to be in the path.
I made a worthless attempt to try to including the Alien src into the project, but doesn't seem to work that way either.
Any ideas would be greatly appreciated. I'd prefer it all be contained in my app, but I'll settle for a solution which involves including the libraries in my project to build and bundle in the distribution if that's the only alternative.
Thanks!
UPDATE:
Ok, thank you Ben Voigt! I think I'm almost there. I've pulled in core.c and struct.c and made sure all the paths are there for libffi. Everything compiles without issue, until I try to call luaopen_alien_core in core.c (the alien.core src file), claiming the identifier is undeclared. I've tried to declare the function signature in my separate source file that's trying to make the call, the compile gets further, but fails complaining of an unresolved external.
Clearly this is likely now a general C++ issue (as I'm only a novice in this area). Here's the general idea of what I have:
//core.c (from Alien project)
(...)
int luaopen_alien_core(lua_State *L) {
alien_register_library_meta(L);
alien_register_callback_meta(L);
alien_register_function_meta(L);
alien_register_buffer_meta(L);
lua_getglobal(L, "alien");
if(lua_isnil(L, -1)) {
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "alien");
}
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "core");
alien_register_main(L);
return 1;
}
//mysource.c (the file attempting to call luaopen_alien_core(L))
void initLua()
{
L = luaL_newstate();
luaL_openlibs(L);
luaopen_alien_core(L);
(...)
}
This fails to start compiling, issuing the error:
error C3861: 'luaopen_alien_core': identifier not found
Which makes sense, so I add the following line to myheader.h:
int luaopen_alien_core(lua_State *L);
This compiles, but fails to link with:
error LNK2001: unresolved external symbol "int __cdecl luaopen_alien_core(struct lua_State *)" (?luaopen_alien_core##YAHPEAUlua_State###Z)
I've tried several things I can think of, with my limited experience, but nothing will satisfy this error. I even tried to move the contents of core.c into mysource.c, but that creates a whole different mess and seemed to be the wrong way to go as it is.
I'm hoping, and imagining, this is something really stupid, but I'm just not sure how to get it to call luaopen_alien_core, which seems to be the final piece I need.
Thanks again!
}
I imagine that the require directive both loads a dynamic library and adds its contents to the active Lua engine.
By linking alien directly into your code, you obviate the need for the dynamic library. But the content enumeration code won't have run, and you can't use require to run it, or else it'll go looking for a DLL file (along with all the DLL dependencies).
So, you should find out what functions that require directive calls after loading the DLL, and call those when creating a Lua engine. Then it will neither be necessary nor allowed for the script to start with require [[Alien/alien]], but Alien objects will be available.