When I try to call libjpeg’s jpeg_create_decompress() function, I get
/usr/include/x86_64-linux-gnu/jconfig.h:8:34: error: invalid suffix '.0' on floating constant
#define LIBJPEG_TURBO_VERSION 1.5.0
^
.../main.swift:49:5: error: use of unresolved identifier 'jpeg_create_decompress'
jpeg_create_decompress(&info)
^~~~~~~~~~~~~~~~~~~~~~
CJPEG.jpeg_CreateDecompress:1:13: note: did you mean 'jpeg_CreateDecompress'?
public func jpeg_CreateDecompress(_ cinfo: j_decompress_ptr!, _ version: Int32, _ structsize: Int)
^
<unknown>:0: error: build had 1 command failures
Now, looking inside jpeglib.h I see
/* Initialization of JPEG compression objects.
* jpeg_create_compress() and jpeg_create_decompress() are the exported
* names that applications should call. These expand to calls on
* jpeg_CreateCompress and jpeg_CreateDecompress with additional information
* passed for version mismatch checking.
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
*/
#define jpeg_create_compress(cinfo) \
jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \
jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
(size_t) sizeof(struct jpeg_decompress_struct))
EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version,
size_t structsize);
EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version,
size_t structsize);
The jpeg_create_decompress isn’t available, probably as stated in the documentation:
Complex macros are used in C and Objective-C but have no counterpart in Swift. Complex macros are macros that do not define constants, including parenthesized, function-like macros. You use complex macros in C and Objective-C to avoid type-checking constraints or to avoid retyping large amounts of boilerplate code. However, macros can make debugging and refactoring difficult. In Swift, you can use functions and generics to achieve the same results without any compromises. Therefore, the complex macros that are in C and Objective-C source files are not made available to your Swift code.
But without this macro, how do I use libjpeg with Swift?
I don't see a way around redefining them in Swift, for example:
class JPEGLibWrapper {
class func jpeg_create_decompress(cinfo: j_decompress_ptr) {
jpeg_CreateDecompress(cinfo, JPEG_LIB_VERSION, MemoryLayout<jpeg_decompress_struct>.size)
}
}
Or in Objective-C:
#interface JPEGLibWrapper : NSObject
+ (void) jpeg_create_decompress:(j_decompress_ptr)cinfo;
#end
#implementation JPEGLibWrapper
+ (void) jpeg_create_decompress:(j_decompress_ptr)cinfo {
jpeg_create_decompress(cinfo);
}
#end
(Better naming could be used...)
EDIT I just noticed you're using Swift on Linux, correct? I don't know how the Swift–C bridging is done on Linux but I guess could do something similar to the Objective-C code but in a C file.
The advantage of declaring an Objective-C or C method/function over doing it in Swift is that in the former you're actually using the complex macro, therefore avoiding (mis)translating it. You just declare a wrapper method/function around it and expose it to Swift.
Source:
https://www.andrewcbancroft.com/2015/01/29/converting-complex-objective-c-macros-swift-functions/
https://medium.com/#YogevSitton/from-objective-c-to-swift-use-complex-define-macros-in-swift-28cdff464fc7
Related
I have some dynamic libraries making available over 200 functions via C calling conventions. I have no access to the source. I'd like to provide these as functions callable by Swift.
Currently I am making each function from the dylibs available via code like this:
public func mainInit() -> Int64 {
let dllMainInitPointer = getFunctionPointer(libHandle, "DllMainInit")
typealias DllMainInitFunction = PtrDllMainInit
let dllMainInit = unsafeBitCast(dllMainInitPointer, to: DllMainInitFunction.self)
return dllMainInit()
}
where PtrDllMainInit is obtained by Swift interpreting the C function prototypes in the header file, in this case:
typedef int64_t (*PtrDllMainInit)(void);
. . .
extern PtrDllMainInit DllMainInit;
which works. But (a) it returns the result of the function, and I'd rather it return the function itself, so it can be called independently, and (b) every use repeats executing the boilerplate code.
It seems that this boilerplate, in every function, could possibly be factored out. (I already factored, behind getFunctionPointer, calling dlsym and checking for missing symbols). Most of the dylib functions are generally more complex than this example, having multiple parameters; writing 200+ functions, like above, is time consuming and prone to error.
Ideally, I'd like a way auto-generate assignments that provide the Swift functions, using the dylib handle, the symbol name, and the C prototype; something like the following:
dllMainInit = magicFunction(libHandle, "DllMainInit", PtrDllMainInit)
In addition to factoring out repetition, one-liners (or, maybe two-liners) like this can be generated simply by processing the header file into this form.
Ultimately, allowing something of this form in the C headers:
typedef int (*PtrProp2)(int64_t key, double time, double llh[3]);
to be converted to a Swift function (closure?), and invoked, thusly:
let prop2 = magicFunction(libHandle, "DllProp2", PtrProp2)
. . .
prop2(id, hours, &vector)
This is a bit tangled, I hope I've explained it well enough.
Edit: Well, this works for simple function I started with:
public func mainInit() -> () -> Int64 {
unsafeBitCast(getFunctionPointer(libHandle,
"DllMainInit"),
to: PtrDllMainInit.self)
}
The parameters of the returned closure can be derived from the .h file. I'll see if this mechanism hold up for more complications.
I've just found out that Swift's private access modifier is file level, as stipulated in the docs under "Access Levels":
Private access in Swift differs from private access in most other languages, as it’s scoped to the enclosing source file rather than to the enclosing declaration. This means that a type can access any private entities that are defined in the same source file as itself, but an extension cannot access that type’s private members if it’s defined in a separate source file.
So this means the following code will compile when the types are in the same file:
class FirstType {
private var privateProperty: String = ""
}
class SecondType {
private let firstType = FirstType()
func messWithFirstType() {
firstType.privateProperty = "👻" // this compiles and works!
}
}
As far as I can see, this breaks encapsulation completely. On the other hand, it might be nice to have some related types grouped together in the same file for readability, especially if the related types are tiny, like enums.
Private extensions are an exception because they are extending the same type the file is meant to contain. And private extensions do bring some nice things.
Are there any other reason, apart from facilitating private extensions, for the file scope private access modifier to be in Swift?
It isn't clear to me why private was originally implemented with regard to files, but rest assured that the Swift folks know this is not the only possible meaning of private and that it isn't ideal for some purposes, and are working to change it. There's already a proposal on the table, accepted for Swift 3, that will turn the current private into fileprivate and add a new level of private that will be scoped to the type rather than the file. You can expect to see this become part of Swift 3 in the very near future.
When you wonder about anything that seems "weird" in Swift, most of the time the answer is "because of Objective-C".
For some perspective, I consider 3 access level common to many modern programming languages:
private: only accessible to the class in which it is defined.
protected: only accessible to the class in which it is defined and its subclasses.
public: accessible to any outside program.
Let's take one step further back, to the world of C. C has no access modifier whatsoever, not being an OOP language. However, in reality, it's closer to having a private / public system. If you want other programs to know your symbols (functions, macros, data types, etc.), you define them in your header (.h) file. If not, you define them in your source (.c) file or a private header file. Whatever program interested in your symbol will include the corresponding header file:
#include "foo.h"
This #include is no more than a compiler-assisted copy & paste. The compiler copies all the symbols in foo.h and redeclare them in your source file.
Since Objective-C is a strict superset of C, every valid C program is also a valid Objective-C program. Objective-C continues this tradition: declare your public methods in the header file, keep private methods declaration to the implementation file:
// ------------------------------------------
// MyClass.h
// ------------------------------------------
#interface MyClass: NSObject
- (void) publicMethod;
#end
// ------------------------------------------
// MyClass.m
// ------------------------------------------
#import "MyClass.h"
// Declare your private methods here.
// You can move this to a separate file, i.e. MyClass+Private.h if you want
#interface MyClass()
- (void) privateMethod;
#end
#implementation MyClas
- (void) publicMethod () { ... }
- (void) privateMethod() { ... }
#end
So at glance, Objective-C seems to inherit C's system of public / private declarations. However, Objective-C is a very dynamic language. You can query its runtime for all methods to a class, private or public. Access control in Objective-C is more about "use what I tell you in the documentation" rather than "this method is off limit to you".
This poses a paradox: how do you implement protected in Objective-C? It has no good answer for that. One common pattern is to move all protected methods into a separate declaration file and import them into the main class and subclass's implementation:
// ------------------------------------------
// MyClass+Protected.h
// ------------------------------------------
#interface MyClass (Protected)
- (void) protectedMethod;
#end
// ------------------------------------------
// MySubClass.m
// ------------------------------------------
#import "MyClass+Protected.h"
...
Swift simply carries on that tradition, for better or worse. There is an accepted proposal to change this in Swift 3. If anything, Chris Lattner and the Swift team has shown little affinity for the past and the legacies of C. You can see evidence of that in Swift 2.2 with the removal of ++ and C-style for loops.
I just pulled the latest doxygen from github, compiled it on my Mac, and ran it on a mix of Objective-C and C++ in .mm files. For some of the the C++ classes, the output HTML makes the methods look like Objective-C. For example, code like:
void Thing::foo(int x)
Is shown in the HTML like:
- (void) foo (int) x
Any way to fix this?
Update
It appears that a forward declared Objective-C class causes a problem. For example, something like this, in a .h file:
#class NSMutableString;
...
class Thing {
public:
int foo(double x);
}
Causes it to render the Thing methods like Objective C. I cut that one line #class NSMutableString and it renders correctly like C++ functions.
C++ classes in .mm files are rendering like Objective-C all the time.
As I heard it is possible to use C++ Code within an iPhone (Objective C) project, I want to use an encryption library which is written in C++. However, the library uses a C++ type struct which uses a constructor, that I can't get right.
The Struct looks like this:
struct SBlock
{
//Constructors
SBlock(unsigned int l=0, unsigned int r=0) : m_uil(l), m_uir(r) {}
//Copy Constructor
SBlock(const SBlock& roBlock) : m_uil(roBlock.m_uil), m_uir(roBlock.m_uir) {}
SBlock& operator^=(SBlock& b) { m_uil ^= b.m_uil; m_uir ^= b.m_uir; return *this; }
unsigned int m_uil, m_uir;
};
full source is available here: http://www.codeproject.com/KB/security/blowfish.aspx
what's the easiest way to get around that issue?
I've read the article about using c++ code on apple's developer site, but that didn't help much.
It's definitely possible and the trick is extremely simple: when you are going to use C++ code in your Objective-C++ applications, name your files .mm instead of .m.
So if you have YourViewController.h and YourViewController.m, rename the latter to be YourViewController.mm. It will cause XCODE to use C++ compiler instead of C compiler with your Objective-C++ code.
YourViewController.mm:
- (void) yourMessage {
// will compile just fine and call the appropriate C++ constructor
SBlock sb(1,1);
}
Just change the filename extension of your .m file to .mm and include the C++ headers. Wow, I type too slow, lol.
I have an Objective-C protocol:
typedef enum {
ViewStateNone
} ViewState;
#protocol ViewStateable
- (void)initViewState:(ViewState)viewState;
- (void)setViewState:(ViewState)viewState;
#end
I'm using this protocol in the following class:
#import "ViewStateable.h"
typedef enum {
ViewStateNone,
ViewStateSummary,
ViewStateContact,
ViewStateLocation
} ViewState;
#interface ViewController : UIViewController <ViewStateable> {
}
#end
I won't go too far into the specifics of my application, but what I'm doing here is typedefing an enumeration in a protocol so that the protocol's methods can take an input value of that type.
I'm then hoping to redeclare or extend that typedef in the classes that conform to that protocol, so that each class can have their own view states. However, I'm running into the following two errors:
Redeclaration of enumerator 'ViewStateNone'
Conflicting types for 'ViewState'
I'm ashamed to admit that my knowledge of C (namely typedefs) is not extensive, so is what I'm trying to do here, firstly, possible and, secondly, sensible?
Cheers friends.
It is neither possible nor sensible. This comes from the fact that typedefs and enums are basically just defines. (Well, not really, but for this purpose, they are.) If you need to do things like this, you might want to review your design (see below).
More info
typedef type newtype;
is (almost) equivalent to
#define newtype type;
and
enum {
ViewStateNone
};
is basically the same as
#define ViewStateNone 1
There are a few finer points withe regards to differences between the two, and the most compelling argument for using enums and typedefs is of course compile time checking of integer constants.
However; once an typedef enum {} type; has been seen, it cannot be unseen, and once it has been seen, its name is reserved for it, and it alone.
There are ways around all of this; but those are paths rarely traveled, and generally for good reason. It quickly becomes incredibly unmanageable.
As a solution, you might want to create a new class, MyViewState, which represents a view state and associated information, which could easily just be a wrapper around an NSInteger.
In closing: Review your design. I fear you might be doing something overly convoluted.
It's certainly not possible in the form you have it, for reasons that the errors fairly succinctly explain. An enum constant can only be declared once in any scope, and similarly a typedef.
Moreover, there's a bit of a conceptual difficulty with defining a type in a protocol that implementors can then redefine. The implementors should be conforming to the type, not adding to it. If the class needs to be able to determine its own set of values, the protocol must use a type that is general enough to hold all those that might be wanted. In this case you could use int or, probably more sensibly, something readable like NSString. You might also add another method to the protocol that will report back the values supported by the implementing class.