i have a questions when i use iOS-Universal-Framework - ios

The iOS-Universal-Framework's page : https://github.com/kstenerud/iOS-Universal-Framework
It is an XCode project template to build universal (arm6, arm7, and simulator) frameworks for iOS.
I have build my framework by use this template,but i got a problem,i have pack all my class in the template,including a macro definition #define kCOMPANYID 2 in a .h file Macro.h,but the problem is ... the kCOMPANYID must can be modified by the one who use my framework,so the kCOMPANYID must define out of the framework,but the problem is , some classes in my framework must use the kCOMPANYIDïĵŒso it is a conflict,i don't know how to do,please help me,thanks.

you should avoid #define as much as possible
one way is to make a setter/getter function to for it
e.g.
// public header file
void SetCompanyId(int value);
// int GetCompanyId(); // it can be in public header or private header
// some .m or .c or .cpp file
static int companyId;
int GetCompanyId() { return copanyId; }
void SetCompanyId(int value) { companyId = value; }
or if the user mush provide a id, just make it a global variable. you can add const to it so the value can't change
// header file in your framework
extern const int kCompanyId;
// some implementation file in user code
const int kCompanyId = 2;
then user must provided a company id otherwise it will have linker error

Related

Dart: how to run static function/code "automatically"?

In Dart (Flutter) I would like to have some static code run without being explicitly invoked.
I tried this:
// File 1
class MyClass {
static int member = 42;
}
int dummy = 42;
and file 2:
// File 2
void main() {
int tmp = MyClass.member;
}
I put a breakpoint on the dummy = 2; line but it seemed to never be invoked.
I also tried:
// File 1
class MyClass {
static int member1 = 42;
static int member2 = SomeOtherClass.someFunc();
}
and file 2:
// File 2
void main() {
int tmp1 = MyClass.member1;
int tmp2 = MyClass.member2;
}
With this, SomeOtherClass.someFunc() was invoked when the int tmp2 = ... line was invoked.
I would like SomeOtherClass.someFunc() to be invoked without explicitly accessing MyClass.member2. I would like it invoked on any of the following triggers:
When the program starts (before main() is called).
OR, when code in a file in which MyClass is imported is invoked for the first time.
Is either of these possible in Dart?
This behavior is intentional and cannot be changed. As jamesdlin also explain, all static variables (class and global) in Dart are lazy evaluated and will first get a value with first attempt to access the value.
This is design is described in the Dart specification followed up with a reason for that design choice:
Static variable declarations with an initializing expression are initializedlazily.
The lazy semantics are given because we do not want a language where one tends to define expensive initialization computations, causing long application startup times. This is especially crucial for Dart, which must support the coding of client applications.
https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf

iOS how to wrapper C++ class in Swift project

I have a static library in C++, and now I want to use this library in my new Swift project. I found that I couldn't use C++ class directly in Swift project, so I have to wrapper this library in OC. Then I have some problem wrapping this:
//AbstractClassA.h
#include <string>
class AbstractClassA {
public:
virtual string getString() = 0;
virtual int getInt() = 0;
virtual ~AbstractClassA() {};
};
//AbstractClassB.h
class AbstractClassB {
public:
virtual void function(int a) = 0;
virtual ~AbstractClassB() {};
};
//ChildA.h
#include "AbstractClassA.h"
#include "AbstractClassB.h"
class ChildA : public AbstractClassA
{
public:
ChildA(int a = 640);
ChildA( AbstractClassB* classb, int a = 640);
virtual ~ChildA();
string getString();
int getInt();
protected:
int a;
string b;
};
How to wrapper these classes in OC? Thanks for any help!
You create an Objective-C++ class that wraps the C++ class. The header file must not contain any C++ features; the file with the implementation must end in .mm to tell Xcode to use the Objective-C++ compiler, not Objective-C.
In the .h file, you'd have an interface for class ChildAWrapper, methods init, initWithInt:, initWithClassB:, initWithClassB:Int: and readonly properties stringValue and intValue.
In the .mm file, you'd have an instance variable of type ChildA*. The init methods create a ChildA object. dealloc deletes it. You implement the properties by calling the methods of the ChildA object, converting the std::string to an NSString*.
Same for ClassB with an Objective-C class ClassBWrapper. There you want a readonly property void* wrappedClass returning a pointer to the the ClassB object, converted to void*, because ChildAWrapper will need that.

using llvm RecursiveASTVisitor for Objective C and iOS

I would like to use clang to preprocess objective C files from an iOS app. I looked over the source code and am trying to implement a pre-processor based on the RecursiveASTVisitor class. However, I seem to be running into many issues that I cannot resolve. I developed a preprocessor to add a "Enter" call at the beginning of each method and an "Exit" call at the end. I also added an "Exit" call before each return statement. I am using the following code to do the instrumentation:
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext; // used for getting additional AST info
std::string funcName;
public:
explicit ExampleVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext())) // initialize private members
{
rewriter.setSourceMgr(astContext->getSourceManager(), astContext->getLangOpts());
}
virtual bool VisitObjCMethodDecl(ObjCMethodDecl *ND) {
funcName = ND->getDeclName().getAsString();
errs() << "Testing function: " << funcName << "\n";
if (ND->hasBody()) {
rewriter.InsertText(ND->getBody()->getSourceRange().getBegin().getLocWithOffset(1), "\nEnter(\""+funcName+"\");\n");
rewriter.InsertText(ND->getBody()->getSourceRange().getEnd(),"Exit(\""+funcName+"\");\n");
}
return true;
}
virtual bool VisitReturnStmt(ReturnStmt *ret) {
rewriter.InsertText(ret->getSourceRange().getBegin(), "\nExit(\""+funcName+"\");\n");
errs() << "** Rewrote ReturnStmt\n";
return true;
}
virtual ~ExampleVisitor() {}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor *visitor; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(CompilerInstance *CI)
: visitor(new ExampleVisitor(CI)) // initialize the visitor
{ }
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(ASTContext &Context) {
/* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file */
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
};
The code compiles. I created a command line executable "instrument". I then used the following command to run this on a simple Objective C program generated by Xcode:
instrument AppDelegate.m --
I run into two problems. First, I get the error: 'UIKit/UIKit.h' file not found. This is one of the includes generated by Xcode. Second, I'm seeing only some of the return statements being processed in the file. Can someone give me some insights into what is happening?
I'm using the 3.7.0 version of llvm.

Has anyone created a MonoTouch binding for the Nuance Dragon Mobile Speech SDK for iOS?

I have the Dragon Mobile SDK running nicely on Windows Phone 7 and I would like to get the equivalent functionality working for iOS. Since the SDK wraps the microphone, it's not really possible to use the .NET assemblies in my MonoTouch project (even if I did have the source). It appears that the best way to do this is to create a binding library (as Miguel describes here).
It sure seems like a lot of work though, and I would love to reuse as opposed to reinventing the wheel if someone's done it already...
Here are some more details for how I got this to work.
I downloaded the binding sample. You may be tempted to skip this step, but you really have to start with this project if you want to get this to work.
I created an objective-c library with Xcode (which I called SpeechKitLibrary) that has a dual purpose - one is to define the SpeechKitApplicationKey (which is an extern dependency that SpeechKit needs):
const unsigned char SpeechKitApplicationKey[] = {...};
and the other is to define a class which utilizes the SpeechKit framework, and links with it. (in Xcode, add the SpeechKit framework in the frameworks section of the project).
The .m file I wrote looks something like this... (you can figure out the .h file - super simple). I'm not 100% sure you need all of this, but I wanted to make sure the static archive library that came out of this step would import the right symbols. You may be able to avoid this somehow, but in my experiments I found that I needed to do something like this...
// the SpeechKitWrapper isn't actually used - rather, it is a way to exercise all the API's that
// the binding library needs from the SpeechKit framework, so that those can be linked into the generated .a file.
#implementation SpeechKitWrapper
#synthesize status;
- (id)initWithDelegate:(id <SKRecognizerDelegate>)delegate
{
self = [super init];
if (self) {
del = delegate;
[self setStatus:#"initializing"];
SpeechKit setupWithID:#"NMDPTRIAL_ogazitt20120220010133"
host:#"sandbox.nmdp.nuancemobility.net"
port:443
useSSL:NO
delegate:nil];
NSString *text = [NSString stringWithFormat:#"initialized. sessionid = %#", [SpeechKit sessionID]];
[self setStatus:text];
SKEarcon* earconStart = [SKEarcon earconWithName:#"beep.wav"];
[SpeechKit setEarcon:earconStart forType:SKStartRecordingEarconType];
voiceSearch = [[SKRecognizer alloc] initWithType:SKDictationRecognizerType
detection:SKLongEndOfSpeechDetection
language:#"en_US"
delegate:delegate];
text = [NSString stringWithFormat:#"recognizer connecting. sessionid = %#", [SpeechKit sessionID]];
[self setStatus:text];
}
return self;
}
#end
I then compiled/linked this static archive for the three different architectures - i386, arm6, and arm7. The Makefile in the BindingSample is the template for how to do this. But the net is that you get three libraries - libSpeechKitLibrary-{i386,arm6,arm7}.a. The makefile then creates a universal library (libSpeechKitLibraryUniversal.a) using the OSX lipo(1) tool.
Only now are you ready to create a binding library. You can reuse the AssemblyInfo.cs in the binding sample (which will show how to create an import on the universal library for all architectures - and will drive some compile flags)...
[assembly: LinkWith ("libSpeechKitLibraryUniversal.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7, ForceLoad = true)]
You compile the ApiDefinition.cs file with btouch as per the Makefile (I think I needed to repeat some of the info in StructsAndEnums.cs to make it work). Note - the only functionality I didn't get to work is the "SetEarcon" stuff - since this is an archive library and not a framework, I can't bundle a wav as a resource file... and I couldn't figure out how to get the SetEarcon method to accept a resource out of my app bundle.
using System;
using MonoTouch.Foundation;
namespace Nuance.SpeechKit
{
// SKEarcon.h
public enum SKEarconType
{
SKStartRecordingEarconType = 1,
SKStopRecordingEarconType = 2,
SKCancelRecordingEarconType = 3,
};
// SKRecognizer.h
public enum SKEndOfSpeechDetection
{
SKNoEndOfSpeechDetection = 1,
SKShortEndOfSpeechDetection = 2,
SKLongEndOfSpeechDetection = 3,
};
public static class SKRecognizerType
{
public static string SKDictationRecognizerType = "dictation";
public static string SKWebSearchRecognizerType = "websearch";
};
// SpeechKitErrors.h
public enum SpeechKitErrors
{
SKServerConnectionError = 1,
SKServerRetryError = 2,
SKRecognizerError = 3,
SKVocalizerError = 4,
SKCancelledError = 5,
};
// SKEarcon.h
[BaseType(typeof(NSObject))]
interface SKEarcon
{
[Export("initWithContentsOfFile:")]
IntPtr Constructor(string path);
[Static, Export("earconWithName:")]
SKEarcon FromName(string name);
}
// SKRecognition.h
[BaseType(typeof(NSObject))]
interface SKRecognition
{
[Export("results")]
string[] Results { get; }
[Export("scores")]
NSNumber[] Scores { get; }
[Export("suggestion")]
string Suggestion { get; }
[Export("firstResult")]
string FirstResult();
}
// SKRecognizer.h
[BaseType(typeof(NSObject))]
interface SKRecognizer
{
[Export("audioLevel")]
float AudioLevel { get; }
[Export ("initWithType:detection:language:delegate:")]
IntPtr Constructor (string type, SKEndOfSpeechDetection detection, string language, SKRecognizerDelegate del);
[Export("stopRecording")]
void StopRecording();
[Export("cancel")]
void Cancel();
/*
[Field ("SKSearchRecognizerType", "__Internal")]
NSString SKSearchRecognizerType { get; }
[Field ("SKDictationRecognizerType", "__Internal")]
NSString SKDictationRecognizerType { get; }
*/
}
[BaseType(typeof(NSObject))]
[Model]
interface SKRecognizerDelegate
{
[Export("recognizerDidBeginRecording:")]
void OnRecordingBegin (SKRecognizer recognizer);
[Export("recognizerDidFinishRecording:")]
void OnRecordingDone (SKRecognizer recognizer);
[Export("recognizer:didFinishWithResults:")]
[Abstract]
void OnResults (SKRecognizer recognizer, SKRecognition results);
[Export("recognizer:didFinishWithError:suggestion:")]
[Abstract]
void OnError (SKRecognizer recognizer, NSError error, string suggestion);
}
// speechkit.h
[BaseType(typeof(NSObject))]
interface SpeechKit
{
[Static, Export("setupWithID:host:port:useSSL:delegate:")]
void Initialize(string id, string host, int port, bool useSSL, [NullAllowed] SpeechKitDelegate del);
[Static, Export("destroy")]
void Destroy();
[Static, Export("sessionID")]
string GetSessionID();
[Static, Export("setEarcon:forType:")]
void SetEarcon(SKEarcon earcon, SKEarconType type);
}
[BaseType(typeof(NSObject))]
[Model]
interface SpeechKitDelegate
{
[Export("destroyed")]
void Destroyed();
}
[BaseType(typeof(NSObject))]
interface SpeechKitWrapper
{
[Export("initWithDelegate:")]
IntPtr Constructor(SKRecognizerDelegate del);
[Export("status")]
string Status { get; set; }
}
}
You now have an assembly that can be referenced by your monotouch application project. The important thing now is to remember to link with all the frameworks that are dependencies (not only SpeeckKit, but also SK's dependencies) - you do this by passing mtouch some additional arguments:
-gcc_flags "-F<insert_framework_path_here> -framework SpeechKit -framework SystemConfiguration -framework Security -framework AVFoundation -framework AudioToolbox"
That's all, folks! Hope this was helpful...
If anyone (kos or otherwise) gets the SetEarcon method to work, please post a solution :-)
Nuance's SDK Agreement is not permissive enough for anyone to even publish bindings for their iOS SDK for use with MonoTouch. But the library itself should work just fine.
That being said, the SDK has only a handful of types to map and would be fairly trivial to RE-do the work anyone else might have already done. You can check out how to bind assemblies using the reference guide here:
http://docs.xamarin.com/ios/advanced_topics/binding_objective-c_types
There's also a BindingSample project that helps users better understand how to bind native components using btouch:
https://github.com/xamarin/monotouch-samples/tree/master/BindingSample
Thanks again Anuj for your answer. I thought I'd leave a tip or two about how to do this. The binding library wasn't difficult to build (still tweaking it but it's not a difficult task).
The more obscure part was figuring out how to get the SpeechKit framework linked. The samples only show how to link a .a or .dylib. After spending a little time with the ld(1) man page on OSX, it looks like the correct ld (and therefore gcc) arguments for linking with a framework are the following:
-gcc_flags "-F<insert_framework_path_here> -framework SpeechKit"
You put this in a textbox in the project properties - under Build :: iPhone Build :: Additional mtouch arguments
Note that -L doesn't work because this isn't a library; also note that -force_load and -ObjC referenced here don't appear necessary because, again, this is a framework and not a library.

Do C++ Templates play nicely with VCL classes?

I'm trying to use C++ Template 'mixins' to create some new VCL components with shared additional functionality. Example...
template <class T> class Mixin : public T
{
private:
typedef T inherited;
// ...additional methods
public:
Mixin(TComponent *owner) : inherited(owner)
{
// .. do stuff here
};
};
Used like this:
class MyLabel : public Mixin<TLabel>
{
....
}
class MyEdit : public Mixin<TEdit>
{
....
}
Now, everything compiles fine, and the mixin stuff seems to work - until I try and save the component to a stream using TStream->WriteComponent, where the inherited properties (eg TLabel.Width/Height/etc.) don't get written. This is even with a 'null' mixin like the one shown above.
My code works fine when just deriving classes directly from TForm, TEdit, etc - and the class is correctly registered with the streaming system.
The quick/simple answer is: no; when dealing with a template, the compiler won't generate the proper descriptors to make streaming working. However, since this has come up before, I peeked under the cover to find out what's missing. And what I found is that it's almost there. So here's a little more information.
Upfront the compiler will never treat a template-based type as a Delphi. For example, do something like this:
void testing()
{
__classid(Mixin<Stdctrls::TLabel>); // Error Here
}
... and you'll see the error
"Error E2242 test.cpp 53: __classid requires Delphi style class type (i.e. class marked __declspec(delphiclass) or derived from System::TObject) in function testing()"
This basically says the compiler does not consider this type/class as compatible with Delphi-classes [i.e. those that derive from TObject]. Internally there's just a flag on the symbol that says whether the type is delphi-compatible or not. And I noticed that I could trick the compiler into marking the type as delphi-style if I forced it to walk up the hierarchy.. which is something it has to do if I create an instance of the object. So, with this hack the error goes away:
void testing()
{
typedef Mixin<Stdctrls::TLabel> __ttype;
std::auto_ptr<__ttype> c2(new __ttype(0));
__classid(Mixin<Stdctrls::TLabel>); // No more errors here
}
But much nicer was actually to use the __declspec(delphiclass) directly on the template, as in:
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
So now that the compiler treats the type as a delphi-style class without hacks, I peeked a little more and found the issue you're probably running into: Delphi classes have the TTypeData.PropCount field - http://docwiki.embarcadero.com/VCL/en/TypInfo.TTypeData - which is a sum of the class' properties, including those of its base classes. Due to the way the various pieces of information are computed, the compiler writes out a '0' for that field when a template is involved:(
You can see this by printing out the PropCount, as in:
#include <Stdctrls.hpp>
#include <cstdio>
#include <memory>
#include <utilcls.h>
class TCppComp : public Classes::TComponent {
int i;
public:
__fastcall TCppComp(TComponent* owner): Classes::TComponent(owner) {};
__published:
__property int AAAA = {read=i, write=i};
};
template <class T>
class __declspec(delphiclass) Mixin : public T {
private:
int i;
typedef T inherited;
public:
__fastcall Mixin(TComponent *owner) : inherited(owner) {};
};
typedef Mixin<TCppComp> TMixinComp;
void showProps(TClass meta) {
PTypeInfo pInfo = PTypeInfo(meta->ClassInfo());
int Count = GetPropList(pInfo, tkAny, NULL);
TAPtr<PPropInfo> List(new PPropInfo[Count]);
std::printf("Class: %s - Total Props:%d\n",
AnsiString(pInfo->Name).c_str(), Count);
GetPropList(pInfo, tkAny, *(reinterpret_cast<PPropList*>(&List)));
for (int i = 0; i < Count; i++) {
AnsiString propName(List[i]->Name);
std::printf("\t%s\n", propName.c_str());
}
}
void test() {
showProps(__classid(TCppComp));
showProps(__classid(TMixinComp));
}
int main() {
test();
return 0;
}
When run the above prints:
Class: TCppComp - Total Props:3
AAAA
Name
Tag
Class: #%Mixin$8TCppComp% - Total Props:0
IOW, Mixin shows up with '0' published properties while its base type has 3:(
I suspect the streaming system relies on this count and that's why inherited properties are not being written out in your setup.
I considered tweaking the generated descriptors at runtime but since we write them to _TEXT it's bound to trigger DEP.
I'll look at the logic that computes the PropCount to see if there's some way to get it to compute the correct number. If time allows, please do open a QC for this: now that I've peek underneath, I believe it would not require much effort to get this working as expected.
Cheers,
Bruneau
PS: In my sample I even had the Mixin publish a property and the compiler generated the correct descriptor for that property; however, the total count was still zero.

Resources