I have a question guys.
I need to assign value to UITextView controller in my iPad app from a C++ function. So, the C++ function return a string and I can see that output in the output window. I merged C++ and XCode objective C by using .mm file. Now, I need to get the value from C++ function and add them in the UITextFiled.
Say for example.
My C++ function is like the following:
.cpp file
void *consumer (void* data)
{
SyncBuffThang<GLOBAL_BUFF_LEN,GLOBAL_BUFFS>* cc =(SyncBuffThang<GLOBAL_BUFF_LEN,GLOBAL_BUFFS>*) data;
affinity("consumer", cons);
for (int ii=0; ii<100; ii++)
{
unsigned char c = cc->get();
cc->res = c;
myVar = c;
cerr << "Consumer Get" << myVar << endl;
f +=c;
}
cerr << "Leaving consumer in method cons" << f << endl;
return 0;
}
int PC9::RunPC()
{
SyncBuffThang<GLOBAL_BUFF_LEN, GLOBAL_BUFFS> pc;
pthread_t p, c;
pthread_create(&p, 0, producer, &pc);
pthread_create(&c, 0, consumer, &pc);
pthread_join(p, 0);
pthread_join(c,0);
}
And the following sows the .mm file code.
#import "PC.h"
#import "PC9.h"
#import "GV.h"
#implementation PC
-(void)callFunctionPC
{
PC9 * myCPlusPlusObj; //A C++ object
myCPlusPlusObj=new PC9();
myCPlusPlusObj-> RunPC();
}
#end
See in the above function I can print the myVar but, I don't know how to access it or view it on UITextFile from my iPad app.
Friends I would really appreciate your help.
Thanks in advance.
-T
Here is the Answer I've been waiting for!!!
HelloWorld.h
#ifndef __Demo1__HelloWorld__
#define __Demo1__HelloWorld__
#include <iostream>
#endif
class HelloWorld {
public:
std::string Mtd_HelloWorld();
};
HelloWorld.cpp
#include "HelloWorld.h"
std::string HelloWorld::Mtd_HelloWorld()
{
std::string output;
output = "This is from C++";
return output;
}
HelloWorldM.h
#import <Foundation/Foundation.h>
#interface HelloWorld_M : NSObject
-(NSString *)CallCPP;
-(UIView *)CreateTextView:(NSString *)input;
#end
HelloWorld.mm
#import "PCViewController.h"
#include "HelloWorld.h"
#include "HelloWorld_M.h"
#implementation HelloWorld_M
-(NSString *)CallCPP
{
HelloWorld * myCPlusPlusObj; //A C++ object
myCPlusPlusObj=new HelloWorld();
std::string res = myCPlusPlusObj-> Mtd_HelloWorld();
NSString *result = [NSString stringWithCString:res.c_str()
encoding:[NSString defaultCStringEncoding]];
return result;
}
-(UIView *)CreateTextView:(NSString *)input
{
UITextView *myTextView = [[UITextView alloc] initWithFrame: CGRectMake (0.0,0.0,320.0,200.0)];
myTextView.text = input;
return myTextView;
}
#end
PCViewController.h
#import <UIKit/UIKit.h>
#import "HelloWorld_M.h"
#interface PCViewController : UIViewController
{
HelloWorld_M *objHelloWorld;
}
- (IBAction)RunHelloWorld:(id)sender;
#end
PCViewController.m
#import "PCViewController.h"
#interface PCViewController ()
#end
#implementation PCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)RunHelloWorld:(id)sender
{
objHelloWorld = [[HelloWorld_M alloc]init];
[self.view addSubview: [objHelloWorld CreateTextView:[objHelloWorld CallCPP]]] ;
}
#end
Related
In my iOS project, I want to call a C++ function from my Swift code that takes an object from my Swift code and returns another object.
So far, following this tutorial and adding a little bit more stuff, I managed to call a C++ function that takes a simple parameter and returns a string:
I create the NativeLibWrapper.h file:
#import <Foundation/Foundation.h>
#interface NativeLibWrapper : NSObject
- (NSString *) sayHello: (bool) boolTest;
#end
I create the NativeLibWrapper.mm file:
#import <Foundation/Foundation.h>
#import "NativeLibWrapper.h"
#import "NativeLib.hpp"
#implementation NativeLibWrapper
- (NSString *) sayHello: (bool) boolTest {
NativeLib nativeLib;
std::string retour = nativeLib.sayHello(boolTest);
return [NSString stringWithCString: retour.c_str() encoding: NSUTF8StringEncoding];
}
#end
I create the NativeLib.hpp file:
#ifndef NativeLib_hpp
#define NativeLib_hpp
#include <stdio.h>
#include <string>
class NativeLib
{
public:
std::string sayHello(bool boolTest);
};
#endif /* NativeLib_hpp */
I create the NativeLib.cpp file:
#include "NativeLib.hpp"
std::string NativeLib::sayHello(bool boolTest)
{
return "Hello C++ : " + std::to_string(boolTest);
}
I add the following in Runner/Runner/Runner-Bridging-Header.h:
#import "NativeLibWrapper.h"
And finally, I call the C++ function in Swift:
NativeLibWrapper().sayHello(true)
But now, let's say that my C++ sayHello() function takes this kind of object as a parameter (so I can access it in the C++ function):
class TestAPOJO {
var value1 = ""
var value2 = false
}
and returns this kind of object (generated from the C++ function but then mapped into a Swift object, or something like that):
class TestBPOJO {
var value3 = 0.0
var value4 = false
}
How can I achieve that?
Thanks.
OK so here is what I did to make it work:
create Objective-C TestAPOJO and TestBPOJO classes:
// TestAPOJO.h:
#import <Foundation/Foundation.h>
#interface TestAPOJO : NSObject
#property NSString *value1;
#property bool value2;
#end
// TestAPOJO.mm:
#import "TestAPOJO"
#implementation TestAPOJO
#end
create C++ TestAPOJOFromC and TestBPOJOFromC classes:
// TestAPOJOFromC.hpp:
#ifndef TestAPOJOFromC_hpp
#define TestAPOJOFromC_hpp
class TestAPOJOFromC
{
public:
TestAPOJOFromC();
~TestAPOJOFromC();
std::string value1;
bool value2;
};
#endif /* TestAPOJOFromC_hpp */
// TestBPOJOFromC.cpp:
#include "TestBPOJOFromC.hpp"
TestBPOJOFromC::TestBPOJOFromC()
{
value1 = "";
value2 = false;
}
TestBPOJOFromC::~TestBPOJOFromC() = default;
in the NativeLibWrapper.h file, add:
- (TestBPOJO *) getTestPOJOS: (TestAPOJO *) testAPOJO;
in the NativeLibWrapper.mm file, add:
- (TestBPOJO *) getTestPOJOS: (TestAPOJO *) testAPOJO {
NativeLib nativeLib;
TestAPOJOFromC *testAPOJOFromC = new TestAPOJOFromC();
testAPOJOFromC->value1 = std::string([testAPOJO.value1 UTF8String]);
testAPOJOFromC->value2 = testAPOJO.value2;
TestBPOJOFromC * testBPOJOFromC = nativeLib.getTestPOJOS(testAPOJOFromC);
TestBPOJO *testBPOJO = [TestBPOJO new];
testBPOJO.value3 = testBPOJOFromC->value3;
testBPOJO.value4 = testBPOJOFromC->value4;
return testBPOJO;
}
I am running an example code form a book, it is about using openCv on IOS device to do video processing. but I got "No viable overloaded '='" error, and i did search the StackOverFlow and found some similar posts and answers, but all solutions does not work for me, so I post code as below, and hope anyone can give some suggestions. Really appreciate it!
This is ViewController.h file:
#import <UIKit/UIKit.h>
#import <opencv2/imgcodecs/ios.h>
#import "CvEffects/RetroFilter.hpp"
#import <opencv2/videoio/cap_ios.h>
#interface ViewController : UIViewController<CvVideoCameraDelegate>
{
CvVideoCamera* videoCamera;
BOOL isCapturing;
RetroFilter::Parameters params;
cv::Ptr<RetroFilter> filter;
uint64_t prevTime;
}
#property (nonatomic, strong) CvVideoCamera* videoCamera;
#property (nonatomic, strong) IBOutlet UIImageView* imageView;
#property (nonatomic, strong) IBOutlet UIToolbar* toolbar;
#property (nonatomic, weak) IBOutlet
UIBarButtonItem* startCaptureButton;
#property (nonatomic, weak) IBOutlet
UIBarButtonItem* stopCaptureButton;
-(IBAction)startCaptureButtonPressed:(id)sender;
-(IBAction)stopCaptureButtonPressed:(id)sender;
#end
This is the ViewController.m file:
#import "ViewController.h"
#import <mach/mach_time.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize imageView;
#synthesize startCaptureButton;
#synthesize toolbar;
#synthesize videoCamera;
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize camera
videoCamera = [[CvVideoCamera alloc]
initWithParentView:imageView];
videoCamera.delegate = self;
videoCamera.defaultAVCaptureDevicePosition =
AVCaptureDevicePositionFront;
videoCamera.defaultAVCaptureSessionPreset =
AVCaptureSessionPreset352x288;
videoCamera.defaultAVCaptureVideoOrientation =
AVCaptureVideoOrientationPortrait;
videoCamera.defaultFPS = 30;
isCapturing = NO;
// Load textures
UIImage* resImage = [UIImage imageNamed:#"scratches.png"];
UIImageToMat(resImage, params.scratches);
resImage = [UIImage imageNamed:#"fuzzy_border.png"];
UIImageToMat(resImage, params.fuzzyBorder);
filter = NULL;
prevTime = mach_absolute_time();
}
- (NSInteger)supportedInterfaceOrientations
{
// Only portrait orientation
return UIInterfaceOrientationMaskPortrait;
}
-(IBAction)startCaptureButtonPressed:(id)sender
{
[videoCamera start];
isCapturing = YES;
params.frameSize = cv::Size(videoCamera.imageWidth,
videoCamera.imageHeight);
if (!filter)
filter = new RetroFilter(params);
}
-(IBAction)stopCaptureButtonPressed:(id)sender
{
[videoCamera stop];
isCapturing = NO;
}
//TODO: may be remove this code
static double machTimeToSecs(uint64_t time)
{
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
return (double)time * (double)timebase.numer /
(double)timebase.denom / 1e9;
}
// Macros for time measurements
#if 1
#define TS(name) int64 t_##name = cv::getTickCount()
#define TE(name) printf("TIMER_" #name ": %.2fms\n", \
1000.*((cv::getTickCount() - t_##name) / cv::getTickFrequency()))
#else
#define TS(name)
#define TE(name)
#endif
- (void)processImage:(cv::Mat&)image
{
cv::Mat inputFrame = image;
BOOL isNeedRotation = image.size() != params.frameSize;
if (isNeedRotation)
inputFrame = image.t();
// Apply filter
cv::Mat finalFrame;
TS(ApplyingFilter);
filter->applyToVideo(inputFrame, finalFrame);
TE(ApplyingFilter);
if (isNeedRotation)
finalFrame = finalFrame.t();
// Add fps label to the frame
uint64_t currTime = mach_absolute_time();
double timeInSeconds = machTimeToSecs(currTime - prevTime);
prevTime = currTime;
double fps = 1.0 / timeInSeconds;
NSString* fpsString =
[NSString stringWithFormat:#"FPS = %3.2f", fps];
cv::putText(finalFrame, [fpsString UTF8String],
cv::Point(30, 30), cv::FONT_HERSHEY_COMPLEX_SMALL,
0.8, cv::Scalar::all(255));
finalFrame.copyTo(image);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (isCapturing)
{
[videoCamera stop];
}
}
- (void)dealloc
{
videoCamera.delegate = nil;
}
#end
And I got the error at two statements:
filter = NULL;
and
filter = new RetroFilter(params);
First issue, assigning the pointer:
filter = Ptr<RetroFilter>(new RetroFilter(params));
Second issue, Nulling the pointer:
filter = cv::Ptr<RetroFilter>::Ptr();
The reason is that the cv::Ptr object does not have overrides that make this simpler. The standard library's smart pointer class does a much nicer job of being easy to use.
The first issue is that the only = operator provided is this:
Ptr& operator = (const Ptr& ptr);
This means that you can't assign a RetroFilter to it, only another cv::Ptr, so you need to wrap the RetroFilter already.
The second issue, similar to the first, there is no override = operator that takes NULL. The best way to express a null cv::Ptr is
cv::Ptr<RetroFilter>::Ptr();
Which, being an instance of cv::Ptr can be assigned using the '=' operator.
Glad I could help!
Many thanks to #KirkSpaziani.
I figured that following code works, but do not know why?
Try filter = cv::Ptr<RetroFilter>(new RetroFilter(params);
filter = cv::Ptr<RetroFilter>::Ptr()
I need to get the usertags for a file in c program.
I am aware of "mdls -name kMDItemUserTags FILENAME" command to get this details. But i need to do it in c code. Is there any way from which i can get the values directly instead of running this command and parsing.
You can do it via the NSURL Resource Key NSURLLabelColorKey which uses an NSColor to specify the colour.
Therefore it cannot be done in C per se, however you can write an Objective-C implementation file with a C function entry point so it can be called from C (as noted by #Alex MDC in the comments you can use CoreFoundation and do it in C directly, but I would always favour Foundation where possible as it's easier to use when using ARC).
Given NSColor is used to specify the colour, you'll need to create a struct to hold the RGB values and translate between that struct and NSColor yourself.
Something like (untested):
OSXFileLabelColour.h:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int isSet; // if 0 then no colour set
float r;
float g;
float b;
} LabelColour;
/* Return 1 for success or 0 for failure */
extern int getFileLabelColour(const char *filename, LabelColour *colour);
#ifdef __cplusplus
} // extern "C"
#endif
OSXFileLabelColour.m:
#import <Foundation/Foundation.h>
#import "OSXFileLabelColour"
int getFileLabelColour(const char *filename, LabelColour *colour)
{
int retval = 0;
NSURL *url = [NSURL fileURLWithPath:#(filename)];
if (url) {
NSColor *nscolor = nil;
NSError *error = nil;
if ([url getResourceValue:&nscolor
forKey:NSURLLabelColorKey
error:&error]) {
if (nscolor) {
CGFloat r, g, b, a;
[nscolor getRed:&r green:&g blue:&b alpha:&a];
colour->isSet = 1;
colour->r = r;
colour->g = g;
colour->b = b;
} else {
colour->isSet = 0;
}
retval = 1;
} else {
NSLog(#"Failed to get colour label for file '%s': %#", filename, [error localizedDescription]);
}
} else {
NSLog(#"Failed to create URL for file '%s'", filename);
}
return retval;
}
In my app i have a C++ class and an Objective-c class working together the following way:
PingPong.h
#ifndef __RSSCPPCallbackTest__PingPong__h
#define __RSSCPPCallbackTest__PingPong__h
#include <iostream>
class PingPong
{
public:
static void requestPingPongWithText(std::string text);
static void eventRequestPingPongWithTextSuccess(std::string successString);
static void eventRequestPingPongWithTextFailure(std::string failureString);
};
#endif
PingPong.cpp
#ifndef __RSSCPPCallbackTest__PingPong__m
#define __RSSCPPCallbackTest__PingPong__m
#include "PingPong.h"
void PingPong::requestPingPongWithText(std::string text)
{
if (text.compare("ping") == 0)
{
PingPong::eventRequestPingPongWithTextSuccess("success ping");
}
else
{
PingPong::eventRequestPingPongWithTextFailure("failure pong");
}
}
#endif
Objective-C class: MainViewController.mm
#implementation MainViewController
/* init, viewDidLoad, etc... */
// Call ping with a button
- (IBAction)sayPing:(id)sender {
NSString *text = #"ping";
PingPong::requestPingPongWithText([text UTF8String]);
}
// Call pong with another button
- (IBAction)sayPong:(id)sender {
NSString *text = #"pong";
PingPong::requestPingPongWithText([text UTF8String]);
}
#end
void PingPong::eventRequestPingPongWithTextSuccess(std::string successString)
{
NSLog(#"successString: %#", [NSString stringWithCString:successString.c_str()
encoding:[NSString defaultCStringEncoding]]);
}
void PingPong::eventRequestPingPongWithTextFailure(std::string failureString)
{
NSLog(#"failureString: %#", [NSString stringWithCString:failureString.c_str()
encoding:[NSString defaultCStringEncoding]]);
}
This works fine. What i would like to do finally is to wrap this into a function with a completion block looking like:
[self requestPingPongWithText: text
completion:^(NSString *successString, NSString *failureString)) completion {
if (successString) {
NSLog(#"successString: %#", successString); }
else if (failureString) {
NSLog(#"failureString: %#", failureString); }
}];
How can i wrap up my existing code to have a function looking like above?
Lets make a new typdef in PingPong.h:
typedef void (^OnComplete)(std::string successString, std::string failureString);
Make a new method for the request by block:
static void requestPingPongWithBlock(std:string text, OnComplete block);
another way, to make it explicit:
static void requestPingPongWithBlock(std:string text, void (^block)(std::string successString, std::string failureString));
implementation in PingPong.cpp:
void PingPong::requestPingPongWithBlock(std::string text, OnComplete block)
{
if (text.compare("ping") == 0)
{
block("success ping", "");
}
else
{
block("", "failure pong");
}
}
in MainViewController.mm
-(void)requestPingPongWithText:(NSString*)text completion:(OnComplete) compblock{
PingPong::requestPingPongWithBlock([text UTF8String],compblock);
}
and you can call it like this way:
[self requestPingPongWithText: text
completion:^(std::string successString, std::string failureString) {
if (successString.length() != 0) {
NSLog([NSString stringWithUTF8String: successString.c_str()]); }
else if (failureString.length() != 0) {
NSLog([NSString stringWithUTF8String: failureString.c_str()]); }
}];
I hope it was helpful ;)
Can someone show me Example of usage Poco::BinaryReader and Poco::BinaryWriter with bynary stream on iOS 5.x -> Objective-C++ ?
Yesterday i send question about "How to create and use C++ classes" but its not answer on my question above.
Poco community forum and OpenFrameworks forum looks like died, so i am here.
Thanks.
Ok, no body wants to help.
I did it myself with God help.
Download OpenFrameworks and configure to your destination project;
Code sample:
#import "AppDelegate.h"
#import "Poco/MemoryStream.h"
#import "Poco/BinaryWriter.h"
#import "Poco/BinaryReader.h"
#implementation AppDelegate{
Poco::BinaryWriter *_myBinaryWriter;
Poco::BinaryReader *_myBinaryReader;
}
#synthesize window = _window;
- (void)dealloc
{
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.rootViewController = [[UIViewController new] autorelease];
int bufferSize = 512;
char *_buffer = (char *)malloc(bufferSize);
// >> WRITE BLOCK <<
Poco::MemoryOutputStream *outStream = new Poco::MemoryOutputStream(_buffer, bufferSize);
_myBinaryWriter = new Poco::BinaryWriter(*outStream);
(*_myBinaryWriter) << 1234567890;
(*_myBinaryWriter) << (std::string)"some string";
(*_myBinaryWriter) << 3.14f;
delete(_myBinaryWriter);
delete(outStream);
// >> READ BLOCK <<
Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(_buffer, bufferSize);
_myBinaryReader = new Poco::BinaryReader(*inStream);
int i = 0;
std::string s;
float f = .0f;
(*_myBinaryReader) >> i >> s >> f;
delete(_myBinaryReader);
delete(inStream);
NSLog(#"ReadInt = '%i'", i);
NSLog(#"ReadString = '%#'", [NSString stringWithUTF8String:s.c_str()]);
NSLog(#"ReadFloat = '%f'", f);
[self.window makeKeyAndVisible];
return YES;
}
#end
have i nice day :)