【问题标题】:C function calling objective C functions调用目标 C 函数的 C 函数
【发布时间】:2012-10-12 07:25:12
【问题描述】:

我的 viewController.m 中有一个 c 函数。

int abc(int a, char* b)
{
//do something
}

我还有一个功能

-(void) callIncomingClass
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    //set the position of the button
    button.frame = CGRectMake(100, 170, 100, 30);

    //set the button's title
    [button setTitle:@"Click Me!" forState:UIControlStateNormal];

    //add the button to the view
    [self.view addSubview:button];
}

现在我想从函数 abc 中调用 callIncomingClass

你建议我怎么做??

我为什么要从 C 函数调用一个 Objective C 方法是,我不能在 C 函数中创建一个按钮或做一些类似的处理。

以下代码是否有效:

int abc(int a, char* b)
{ 
    ViewController * tempObj = [[ViewController alloc] init];
    [tempObj callIncomingClass];
}

编辑:我在做什么的大图景 有一个 c 库,即 library.c 和 library.h 文件。 library.h 文件有一个具有回调函数的结构。这些需要分配函数指针。所以我有一个带有签名 int abc(int,char*) 的 c 函数,它要分配给结构中的回调函数。

这个函数 abc 在 ViewController.m 中定义。 理想情况下,我希望它在单独的文件中定义。但这也没关系。

所以现在,回调事件发生了,我想在视图上创建一个带有一些操作的 UIButton。由于我无法从 c 函数创建 UIButton,因此我正在调用 ViewController 类的目标 C 方法,该方法创建 UIButton。

希望能清楚地说明我打算如何使用它。

【问题讨论】:

  • 你可以这样做......但你需要参考self。 c函数不是对象的一部分..所以它不知道self是什么。
  • 您能说得更具体一点吗?我可以做2中的哪一个??从 C 函数调用目标 c 函数?还是从 C 函数创建 UIButton??
  • 如果您有一个现有的ViewController 实例,那将创建一个全新的实例,这可能不是您想要的。请笼统地描述您要完成的工作。如果abc()是一个不能改变签名的回调函数,它在哪里定义,它有什么作用? ViewController实例是设置回调函数的对象吗?
  • 有时当您将 c 函数作为回调时,它会为您提供 void* 参数以将您自己的数据传递到您的实现中。为什么这里不是这种情况/C 库是做什么的?否则解决这个问题的唯一方法是使用全局变量(这几乎不是答案。)

标签: objective-c c cocoa-touch function


【解决方案1】:

由于其他人和我自己的说法,您的按钮没有显示:您需要ViewController 的现有实例。您正在创建一个全新的 ViewController 实例,它永远不会出现在屏幕上或被推送等。

您可以通过使用指向现有实例的全局变量来完成您需要做的事情。

你的 .m 应该是这样的:

#import "ViewController.h"

static ViewController *viewController = nil;

@implementation ViewController

- (id)init {
    if ((self = [super init])) {
         viewController = self;
    }
    return self;
}

- (void)dealloc {
    viewController = nil;
}

-(void) callIncomingCreateButton {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    //set the position of the button
    button.frame = CGRectMake(100, 170, 100, 30);
    //set the button's title
    [button setTitle:@"Click Me!" forState:UIControlStateNormal];
    //add the button to the view
    [self.view addSubview:button];
}

- (IBAction)DemoCall:(id)sender {
    callIncoming(1, "a");
}

@end

int callIncoming(int a, char* b) {
    [viewController callIncomingCreateButton];
    return a;
}

【讨论】:

  • 是的,这可能是一个解决方案,但在我的情况下,我无法更改 C 函数 abc 的签名,因为它是在其他地方分配的回调函数。跨度>
  • 您能概括地描述您想要完成的任务吗?
  • @Vinu:根据您在其他问题中获得的结果更新了我的答案...
  • 谢谢你,@NSGod。代码+例子+解释说得很清楚。但只有一个疑问,这是最有效的方式吗?还是这是唯一的方法??如果是后者,可以在应用中使用吗?
【解决方案2】:

您需要访问正确的ViewController* / 实例,而不是任何旧实例。如果您的 C 函数签名不允许您通过 void* 或类似方法传入一些任意数据,那么您需要使用类方法和静态变量来保存临时指针,如下所示。

在您的 Objective C 文件中:

static ViewController* cLibReceiver = NULL;

+(void) callIncomingClassOuter {
    [cLibReceiver callIncomingClass];
}

-(void) beforeTriggerCLibrary {
    cLibReceiver = self;
}

在你的(不同的)Objective C 文件中,abc() 在:

int abc(int a, char* b)
{ 
    [ViewController callIncomingClassOuter];
}

在你触发 C 库的地方,你需要这样做:

[theViewController beforeTriggerCLibrary]; // could be self, depending on context

c_library_call();

// optionally set cLibReciever back to NULL.

注意:我可能在方法头等方面有一些语法错误,我对目标 C 调用约定并不完全熟悉。类方法肯定是+

注意 2:您可能不允许像这样扩展系统类 - 您可能需要定义自己的子类。同样,对 Objective C 不够熟悉。

【讨论】:

  • stackoverflow.com/questions/12856000/… 这就是我使用它的方式。
  • 我的回答也适用于该问题,但我很确定将其复制并粘贴到那里是违反指导方针的。您仍然需要从任意范围访问相关的ViewController,这是这样做的方式/一种方式。
  • @tehwalrus:和这个问题完全相同。您对全局变量有正确的想法,尽管没有必要将其设为类方法...
  • @NSGod 同意,转发。类方法提供安全性(假设我们想要一个 static 而不是真正的全局变量),并且需要静态方法的原因是 OP 说他们希望能够将 c 函数移出类实现文件 - 静态方法让他们这样做(并很好地封装它。)
【解决方案3】:

假设您在一个 Objective-C 源文件中,从 C 函数调用 Objective-C 函数的工作方式与从任何其他 Objective-C 函数调用 Objective-C 函数完全相同。在任何一种情况下,如果你有一个指针 ptr 指向你想要调用函数的对象,你写

[ptr callIncomingClass];

当然,在任何一种情况下,您都需要以某种方式拥有指向要调用该函数的对象的指针。如果您在 Objective-C 函数(即实例方法)中,则此类指针的通常“源”是(a)当您在与当前运行的方法相同的对象上调用方法时,隐式“自我”指针,( b) 调用当前运行方法的对象的某个实例变量,(c) 当前运行的函数或方法的参数,(d) 全局变量或其他函数调用的结果。在纯 C 语言中,您可以使用 (c) 和 (d),但不能使用 (a) 和 (b),因为您没有 self

【讨论】:

  • okie,所以这必须在理想情况下工作: int abc(int a, char* b){ ViewController * tempObj = [[ViewController alloc] init]; [tempObj callIncomingClass];}
  • 看起来不错,只要确保tempObj 以某种方式再次被释放。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-30
  • 2013-06-24
  • 2020-08-11
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
相关资源
最近更新 更多