moved PyHandler to ObjC class

This commit is contained in:
relikd
2018-07-25 23:14:43 +02:00
parent e9ec28fd90
commit db3ef5a22a
6 changed files with 126 additions and 45 deletions

View File

@@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1968E0AE14B8E8A90E194980 /* PyHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1968EF7567E06D2A5BB3481A /* PyHandler.m */; };
544FBD4521064AEB008A260C /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 544FBD4421064AEB008A260C /* Python.framework */; }; 544FBD4521064AEB008A260C /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 544FBD4421064AEB008A260C /* Python.framework */; };
544FBD4721064B2F008A260C /* getFeed.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4621064B2F008A260C /* getFeed.py */; }; 544FBD4721064B2F008A260C /* getFeed.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4621064B2F008A260C /* getFeed.py */; };
544FBD4921064DF0008A260C /* feedparser521.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4821064DF0008A260C /* feedparser521.py */; }; 544FBD4921064DF0008A260C /* feedparser521.py in Resources */ = {isa = PBXBuildFile; fileRef = 544FBD4821064DF0008A260C /* feedparser521.py */; };
@@ -17,10 +18,11 @@
54ACC28C21061B3C0020715F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC28B21061B3C0020715F /* main.m */; }; 54ACC28C21061B3C0020715F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC28B21061B3C0020715F /* main.m */; };
54ACC29521061E270020715F /* NewsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29421061E270020715F /* NewsController.m */; }; 54ACC29521061E270020715F /* NewsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29421061E270020715F /* NewsController.m */; };
54ACC29821061FBA0020715F /* Preferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29721061FBA0020715F /* Preferences.m */; }; 54ACC29821061FBA0020715F /* Preferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29721061FBA0020715F /* Preferences.m */; };
54ED7BDA2107CE5500AC8248 /* PyHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54ED7BD92107CE5500AC8248 /* PyHandler.cpp */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1968E7919BAA36F042FCB717 /* PyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PyHandler.h; sourceTree = "<group>"; };
1968EF7567E06D2A5BB3481A /* PyHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PyHandler.m; sourceTree = "<group>"; };
544FBD4421064AEB008A260C /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; }; 544FBD4421064AEB008A260C /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; };
544FBD4621064B2F008A260C /* getFeed.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = getFeed.py; sourceTree = "<group>"; usesTabs = 0; }; 544FBD4621064B2F008A260C /* getFeed.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = getFeed.py; sourceTree = "<group>"; usesTabs = 0; };
544FBD4821064DF0008A260C /* feedparser521.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = feedparser521.py; sourceTree = "<group>"; usesTabs = 0; }; 544FBD4821064DF0008A260C /* feedparser521.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = feedparser521.py; sourceTree = "<group>"; usesTabs = 0; };
@@ -37,7 +39,6 @@
54ACC29421061E270020715F /* NewsController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NewsController.m; sourceTree = "<group>"; }; 54ACC29421061E270020715F /* NewsController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NewsController.m; sourceTree = "<group>"; };
54ACC29621061FBA0020715F /* Preferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Preferences.h; sourceTree = "<group>"; }; 54ACC29621061FBA0020715F /* Preferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Preferences.h; sourceTree = "<group>"; };
54ACC29721061FBA0020715F /* Preferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Preferences.m; sourceTree = "<group>"; }; 54ACC29721061FBA0020715F /* Preferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Preferences.m; sourceTree = "<group>"; };
54ED7BD92107CE5500AC8248 /* PyHandler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PyHandler.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -60,6 +61,17 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
549369F421091E6D001AF895 /* python */ = {
isa = PBXGroup;
children = (
1968E7919BAA36F042FCB717 /* PyHandler.h */,
1968EF7567E06D2A5BB3481A /* PyHandler.m */,
544FBD4621064B2F008A260C /* getFeed.py */,
544FBD4821064DF0008A260C /* feedparser521.py */,
);
path = python;
sourceTree = "<group>";
};
54ACC27321061B3B0020715F = { 54ACC27321061B3B0020715F = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -80,9 +92,7 @@
54ACC27E21061B3B0020715F /* baRSS */ = { 54ACC27E21061B3B0020715F /* baRSS */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
54ED7BD92107CE5500AC8248 /* PyHandler.cpp */, 549369F421091E6D001AF895 /* python */,
544FBD4621064B2F008A260C /* getFeed.py */,
544FBD4821064DF0008A260C /* feedparser521.py */,
54ACC27F21061B3B0020715F /* AppDelegate.h */, 54ACC27F21061B3B0020715F /* AppDelegate.h */,
54ACC28021061B3B0020715F /* AppDelegate.m */, 54ACC28021061B3B0020715F /* AppDelegate.m */,
54ACC29321061E270020715F /* NewsController.h */, 54ACC29321061E270020715F /* NewsController.h */,
@@ -179,9 +189,9 @@
54ACC29521061E270020715F /* NewsController.m in Sources */, 54ACC29521061E270020715F /* NewsController.m in Sources */,
54ACC28421061B3B0020715F /* baRSS.xcdatamodeld in Sources */, 54ACC28421061B3B0020715F /* baRSS.xcdatamodeld in Sources */,
54ACC28C21061B3C0020715F /* main.m in Sources */, 54ACC28C21061B3C0020715F /* main.m in Sources */,
54ED7BDA2107CE5500AC8248 /* PyHandler.cpp in Sources */,
54ACC28121061B3B0020715F /* AppDelegate.m in Sources */, 54ACC28121061B3B0020715F /* AppDelegate.m in Sources */,
54ACC29821061FBA0020715F /* Preferences.m in Sources */, 54ACC29821061FBA0020715F /* Preferences.m in Sources */,
1968E0AE14B8E8A90E194980 /* PyHandler.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -313,6 +323,10 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_WARN_CXX0X_EXTENSIONS = YES;
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CODE_SIGN_ENTITLEMENTS = baRSS/baRSS.entitlements; CODE_SIGN_ENTITLEMENTS = baRSS/baRSS.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
@@ -322,6 +336,11 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_LABEL = YES;
INFOPLIST_FILE = baRSS/Info.plist; INFOPLIST_FILE = baRSS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -340,6 +359,10 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_WARN_CXX0X_EXTENSIONS = YES;
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CODE_SIGN_ENTITLEMENTS = baRSS/baRSS.entitlements; CODE_SIGN_ENTITLEMENTS = baRSS/baRSS.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
@@ -349,6 +372,11 @@
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_STRICT_SELECTOR_MATCH = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_LABEL = YES;
INFOPLIST_FILE = baRSS/Info.plist; INFOPLIST_FILE = baRSS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

View File

@@ -21,7 +21,7 @@
// SOFTWARE. // SOFTWARE.
#import "AppDelegate.h" #import "AppDelegate.h"
#import "PyHandler.cpp" #import "PyHandler.h"
@interface AppDelegate () @interface AppDelegate ()
@property (strong) NSStatusItem *statusItem; @property (strong) NSStatusItem *statusItem;
@@ -35,20 +35,21 @@
} }
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
self.statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength]; self.statusItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength];
self.statusItem.title = @"me"; self.statusItem.title = @"me";
self.statusItem.menu = self.statusMenu; self.statusItem.menu = self.statusMenu;
int a[] = {2017,8,9,13,9,59,0,0,0};
printf("will init\n"); printf("will init\n");
pyhandler_init(); [PyHandler prepare];
printf("done\n"); printf("done\n");
printf("%s", pyhandler_getWithDateArr([@"https://feeds.feedburner.com/simpledesktops" UTF8String], NULL, a)); NSDictionary * obj = [PyHandler getFeed:@"https://feeds.feedburner.com/simpledesktops" withEtag:nil andModified:nil];
NSLog(@"obj = %@", obj);
[self quitClicked:nil]; [self quitClicked:nil];
} }
- (void)applicationWillTerminate:(NSNotification *)aNotification { - (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application [PyHandler shutdown];
} }
#pragma mark - Core Data stack #pragma mark - Core Data stack

29
baRSS/python/PyHandler.h Normal file
View File

@@ -0,0 +1,29 @@
//
// The MIT License (MIT)
// Copyright (c) 2018 Oleg Geier
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import <Foundation/Foundation.h>
@interface PyHandler : NSObject
+ (void)prepare; // must be called before getFeed
+ (void)shutdown;
+ (NSDictionary *)getFeed:(NSString *)url withEtag:(NSString *)etag andModified:(NSString *)modified;
@end

View File

@@ -20,68 +20,96 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
#include <stdio.h> #import "PyHandler.h"
#include <Python/Python.h> #import <Python/Python.h>
#include <CoreFoundation/CoreFoundation.h>
static PyObject *parseFeed; static PyObject *parseFeedModule;
PyObject* appBundlePath() { @implementation PyHandler
+ (PyObject*)appBundlePath {
CFBundleRef mainBundle = CFBundleGetMainBundle(); CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef appPath = CFBundleCopyResourcesDirectoryURL(mainBundle); CFURLRef appPath = CFBundleCopyResourcesDirectoryURL(mainBundle);
CFURLRef absolutePath = CFURLCopyAbsoluteURL(appPath); CFURLRef absolutePath = CFURLCopyAbsoluteURL(appPath);
CFStringRef path = CFURLCopyFileSystemPath(absolutePath, kCFURLPOSIXPathStyle); CFStringRef path = CFURLCopyFileSystemPath(absolutePath, kCFURLPOSIXPathStyle);
const char *resourcePath = CFStringGetCStringPtr(path, CFStringGetSystemEncoding()); PyObject * pyStr = PyString_FromString(CFStringGetCStringPtr(path, CFStringGetSystemEncoding()));
// const char *resourcePath = [[[NSBundle mainBundle] resourcePath] UTF8String]; // const char *resourcePath = [[[NSBundle mainBundle] resourcePath] UTF8String];
CFRelease(path); CFRelease(path);
CFRelease(absolutePath); CFRelease(absolutePath);
CFRelease(appPath); CFRelease(appPath);
return PyString_FromString(resourcePath); return pyStr;
} }
void pyhandler_init() { + (void)prepare {
Py_Initialize(); Py_Initialize();
PyObject *sys = PyImport_Import(PyString_FromString("sys")); PyObject *sys = PyImport_Import(PyString_FromString("sys"));
PyObject *sys_path_append = PyObject_GetAttrString(PyObject_GetAttrString(sys, "path"), "append"); PyObject *sys_path_append = PyObject_GetAttrString(PyObject_GetAttrString(sys, "path"), "append");
PyObject *resourcePath = PyTuple_New(1); PyObject *resourcePath = PyTuple_New(1);
PyTuple_SetItem(resourcePath, 0, appBundlePath()); PyTuple_SetItem(resourcePath, 0, [self appBundlePath]);
PyObject_CallObject(sys_path_append, resourcePath); PyObject_CallObject(sys_path_append, resourcePath);
// import MyModule # this is in my project folder // import MyModule # this is in my project folder
PyObject *myModule = PyImport_Import(PyString_FromString("getFeed")); PyObject *myModule = PyImport_Import(PyString_FromString("getFeed"));
parseFeed = PyObject_GetAttrString(myModule, "parse"); parseFeedModule = PyObject_GetAttrString(myModule, "parse");
} }
void pyhandler_shutdown() { + (void)shutdown {
PyObject_Free(parseFeed); PyObject_Free(parseFeedModule);
Py_Finalize(); Py_Finalize();
} }
char* pyhandler_run(PyObject *args) { + (char*)run:(PyObject*)args {
if (parseFeed && PyCallable_Check(parseFeed)) { if (parseFeedModule && PyCallable_Check(parseFeedModule)) {
PyObject *result = PyObject_CallObject(parseFeed, args); PyObject *result = PyObject_CallObject(parseFeedModule, args);
if (result != NULL && PyObject_TypeCheck(result, &PyString_Type)) if (result != NULL && PyObject_TypeCheck(result, &PyString_Type))
return PyString_AsString(result); return PyString_AsString(result);
} }
return NULL; return NULL;
} }
char* pyhandler_getWithDateStr(const char * url, const char * etag, void * date) { + (char *)run:(const char *)url withEtag:(const char *)etag andDateString:(const char *)date {
return pyhandler_run(Py_BuildValue("(z z z)", url, etag, date)); if (!Py_IsInitialized())
return NULL;
return [self run:Py_BuildValue("(z z z)", url, etag, date)];
} }
char* pyhandler_getWithDateArr(const char * url, const char * etag, int * d) { + (char *)run:(const char *)url withEtag:(const char *)etag andDateArray:(int *)d {
if (!Py_IsInitialized())
return NULL;
if (d == NULL || abs(d[8]) > 1) { // d[8] == tm_isdst (between -1 and 1). Array size must be 9 if (d == NULL || abs(d[8]) > 1) { // d[8] == tm_isdst (between -1 and 1). Array size must be 9
return pyhandler_run(Py_BuildValue("(z z z)", url, etag, NULL)); return [self run:Py_BuildValue("(z z z)", url, etag, NULL)];
} }
return pyhandler_run(Py_BuildValue("(z z [iiiiiiiii])", url, etag, return [self run:Py_BuildValue("(z z [iiiiiiiii])", url, etag,
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8])); d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8])];
} }
+ (NSDictionary *)getFeed:(NSString *)url withEtag:(NSString *)etag andModified:(NSString *)modified {
const char* u = NULL;
const char* e = NULL;
const char* m = NULL;
if (url && url.length > 0)
u = [url UTF8String];
if (etag && etag.length > 0)
e = [etag UTF8String];
if (modified && modified.length > 0)
m = [modified UTF8String];
char *data = [self run:u withEtag:e andDateString:m];
printf("JSON result:\n%s\n\n", data);
if (data == NULL) return nil;
NSError *error = nil;
id object = [NSJSONSerialization JSONObjectWithData:
[[NSString stringWithUTF8String:data] dataUsingEncoding:NSUTF8StringEncoding]
options:0 error:&error];
// @see https://docs.python.org/3/c-api/index.html if (error || !object || ![object isKindOfClass:[NSDictionary class]]) {
return nil;
}
return object;
}
// @see: https://docs.python.org/3/c-api/index.html
/* PyObject *ObjcToPyObject(id object) /* PyObject *ObjcToPyObject(id object)
{ {
if (object == nil) { if (object == nil) {
@@ -123,5 +151,6 @@ char* pyhandler_getWithDateArr(const char * url, const char * etag, int * d) {
NSLog(@"ObjcToPyObject() could not convert Obj-C object to PyObject."); NSLog(@"ObjcToPyObject() could not convert Obj-C object to PyObject.");
return NULL; return NULL;
} }
} */ }*/
@end

View File

@@ -102,13 +102,7 @@ def prepareResult(obj):
def parse(url, etag=None, modified=None): def parse(url, etag=None, modified=None):
print "mod:", modified
if isinstance(modified, list): if isinstance(modified, list):
modified = time.struct_time(modified) modified = time.struct_time(modified)
print url d = fp.parse(url, etag=etag, modified=modified)
print etag return json.dumps(prepareResult(d), separators=(',', ':'))
print modified
return '[{"name":"joe","title":"none"},{"value":24}]'
# d = fp.parse(url, etag=etag, modified=modified)
# return json.dumps(prepareResult(d), separators=(',', ':'))