簡體   English   中英

在Objective-C完成塊中運行C回調函數

[英]Running a C callback function inside an Objective-C completion block

我一直在用kivy / python制作應用程序,我需要用obj-c調用一些ios框架。 所以我用python-> cython-> c-> obj-c-> framework做了幾層包裝。 到目前為止,我已經完成了所有工作,直到回調功能一直返回到python。 現在,回調在cython-> C-> obj-c層之間的某個地方失敗(從來沒有在cython中打過我的打印)。 我感覺像是因為我試圖將user_func作為C函數而不是像obj-c函數來調用。 我應該如何在obj-c內部運行C回調函數? 我已經在代碼中添加了打印內容(無法逐步完成我的設置方式),它會打印生成的令牌,然后立即在user_func上崩潰。 它也永遠不會到達我的cython文件中的回調函數。 因此,兩者之間的某個地方是崩潰的根源。

- (void) retrieveTokenObjC:(char*)myKey andcardNumber:(char*)cardNumber andexpMonth:(int)expMonth andexpYear:(int)expYear andcvc:(char*)cvc anduser_func:(tokenfunc)user_func anduser_data:(void*)user_data {

    NSString* NScardNumber = [NSString stringWithUTF8String:cardNumber];
    NSString* NScvc = [NSString stringWithUTF8String:cvc];

    STPCardParams *cardParams = [[STPCardParams alloc] init];
    cardParams.number = NScardNumber;
    cardParams.expMonth = expMonth;
    cardParams.expYear = expYear;
    cardParams.cvc = NScvc;

    NSString *myPublishableKey = [NSString stringWithUTF8String:myKey];
    STPAPIClient *apiClient = [[STPAPIClient alloc] initWithPublishableKey:myPublishableKey];

    [apiClient createTokenWithCard:cardParams completion:^(STPToken *token,NSError *error) {

        if (token == nil || error != nil) {
            const char* errorChar = [error.localizedDescription UTF8String];
            user_func(errorChar,user_data);
        } else {
            const char* tokenChar = [token.tokenId UTF8String];
            user_func(tokenChar,user_data);
        }
    }];
}

之后,它進入obj-c標頭

#import <Foundation/Foundation.h>
typedef void (*tokenfunc) (const char *name, void *user_data);

@interface retToken : NSObject
- (void) retrieveTokenObjC:(char*)myKey andcardNumber:(char*)cardNumber andexpMonth:(int)expMonth andexpYear:(int)expYear andcvc:(char*)cvc anduser_func:(tokenfunc)user_func anduser_data:(void*)user_data;
@end

然后將其放入cython的AC包裝器中。

#include "stripe_ios_c.h"
#include "stripe_ios_imp.h"

    void retrieveToken(char* myKey, char* cardNumber, int expMonth, int expYear, char* cvc,tokenfunc user_func, void *user_data){
        retToken* retrieveToken = [[retToken alloc] init];
        [retrieveToken retrieveTokenObjC:myKey andcardNumber:cardNumber andexpMonth:expMonth andexpYear:expYear andcvc:cvc anduser_func:user_func anduser_data:user_data];
    }

然后是c包裝的頭文件

typedef void (*tokenfunc)(const char *name, void *user_data);
void retrieveToken(char* myKey, char* cardNumber, int expMonth, int expYear, char* cvc,tokenfunc user_func, void *user_data);

最后是cython代碼

__all__ = ['StripeWrapper']

cdef extern from "stripe_ios_c.h":
    ctypedef void (*tokenfunc)(const char *name, void *user_data)
    void retrieveToken(char* myKey, char* cardNumber, int expMonth, int expYear, char* cvc,tokenfunc user_func, void *user_data)

class StripeWrapper():

    def __init__(self,**kwargs):
        foo = 'bar'
        pass

    def getToken(self,tokenCallback,myKey,cardNumber,expMonth,expYear,cvc):

        cdef bytes myKey_bytes = myKey.encode('utf-8')
        cdef char* myKey_string = myKey_bytes
        cdef bytes cardNumber_bytes = cardNumber.encode('utf-8')
        cdef char* cardNumber_string = cardNumber_bytes
        cdef bytes cvc_bytes = cvc.encode('utf-8')
        cdef char* cvc_string = cvc_bytes

        print myKey_bytes
        print cardNumber_bytes
        print cvc_bytes
        print myKey_string
        print cardNumber_string
        print cvc_string

        retrieveToken(myKey_bytes, cardNumber_bytes, expMonth, expYear, cvc_bytes, callback, <void*>tokenCallback)
        print 'Debug 1'

cdef void callback(const char *name, void *tokenCallback):
    print 'callback debug'
    (<object>tokenCallback)(name.decode('utf-8'))

更新:我已經跟蹤了問題,我的回調函數執行了該問題,因為python回調在此途中被釋放了。

我解決了這個問題。 如果您離開主文件/當前文件,則此處的cython回調的示例https://github.com/cython/cython/blob/master/Demos/callback/run_cheese.py將不起作用。 這是因為在您離開該文件的那一刻,內存已被釋放。 推送python對象並使用后

cdef void callback(const char *name, void *tokenCallback):
    (<object> tokenCallback).token = (name.decode('utf-8'))

我覺得cython是example是一個不好的例子,應該使用一個對象來發送回調,這樣可以避免很多挫敗感,但最終成功!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM