从 iOS 中的 C 函数内更新 UI 线程

发布于 2024-11-06 08:38:24 字数 1117 浏览 0 评论 0原文

我正在使用 C 程序来尝试在我的 iOS 应用程序中使用它,并尽可能少地进行修改。 C 程序对一组输入执行大量计算。

在 iOS 方面,我使用以下代码创建一个线程来运行计算,并且还有一种机制来报告完成时的情况(目前,它在完成时更新 UILabel os“testLabel”)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    char *testChar = startProgram( nx, ny, nz ); // this is where I call the C program 

    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *tempString = [[NSString alloc]initWithCString: testChar ];

        testLabel.text = tempString;

        [tempString release];

    });
});

:工作后,我得到结果,并且我的 UI 保持响应。

但是,我希望在计算进行时从 C 例程通信回 UI,以便获取状态以及增量地传回一些数据。

所以我的 C 程序会是这样的:

char* startProgram( int nx, int ny, int nz )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

我在这里看到一个关于传递“self”的线程,但我不认为上面传递的“self”将是我的类“self”。另外,我尝试了一下,在 C 端出现错误,说它无法识别“id”类型。我将“id”的类型更改为类名,它告诉我参数错误。

关于实现这一点的最佳方法有什么想法吗?

感谢您的帮助。

I am working with a C program to try and use it in my iOS application with as little modification as possible. The C program performs a lot of calculations on a set of inputs.

On the iOS side, I am using the following code to create a thread to run the calculations, and also to have a mechanism to report when it is complete (currently, it updates a UILabel os "testLabel" when complete):

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    char *testChar = startProgram( nx, ny, nz ); // this is where I call the C program 

    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *tempString = [[NSString alloc]initWithCString: testChar ];

        testLabel.text = tempString;

        [tempString release];

    });
});

This seems to work, I get my results, and my UI stays responsive.

However, I am wanting to communicate from the C routine back to the UI while the calculations are going on in order to get status as well as to pass some data back incrementally.

So my C program would be something like this:

char* startProgram( int nx, int ny, int nz )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

I saw a thread on here about passing "self", but I don't think the "self" if passed above would be my class "self". In addition, I tried that and got an error on the C-side of things, saying that it did not recognize the type "id". I changed the type of "id" to the class name, and it told me the parameter was wrong.

Any ideas on the best way to implement this?

Thank you for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

留蓝 2024-11-13 08:38:24

声明一个全局 c void*

void* sipUACObj;

并在类初始值设定项中为其分配 Objective-C 类对象

sipUACObj = self;

现在,每当您需要从 C 函数调用某些内容时,请执行以下操作,

  ObjcClass *obj = (ObjcClass*) sipUACObj;
  [obj someMethod:arg1 Arg2:arg2];

这将调用相应的 Objective-C 函数,您可以调用您的主 UI 线程在那个函数中。

您可以创建一个单例类,并在初始化时将其分配给 void 指针,然后在 C 函数中执行所需的操作。

declare a global c void*

void* sipUACObj;

And assign it the objective-c class object in your class initializer

sipUACObj = self;

Now whenever you need to invoke something from C function do the following,

  ObjcClass *obj = (ObjcClass*) sipUACObj;
  [obj someMethod:arg1 Arg2:arg2];

This will call the corresponding objective-C function and you can invoke ur main UI thread in that function.

You could create a singleton class and assign it to the void pointer in its initialization and then do the needful in ur C function.

迷鸟归林 2024-11-13 08:38:24

也许您想要的是有一个块作为回调,用于向调用者报告部分结果。像这样的东西:

char* startProgram( int nx, int ny, int nz, void(^reportBackToUI)(int) )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

然后客户端可以使用类似的东西调用 startProgram

return startProgram(42, 12, 20, ^(int someResults) {
           dispatch_async(dispatch_get_main_queue(), ^{
              // Update UI in some way.
           });         
       });

这样你的代码将不依赖于客户端做什么或如何使用进度回调。这也是很好的依赖注入。

如果无法使用块(模型代码可能需要纯 C 才能在其他平台上工作?),那么您可以将块切换为函数指针。

Maybe what you want is to have a block as a callback for reporting back partial results to the caller. Something like this:

char* startProgram( int nx, int ny, int nz, void(^reportBackToUI)(int) )
{
    setupEverything(); // this is just pseudo code for clarity
    for( int i = 0; i < nz; i++ )
    {
        doMajorCalculations();

        reportBackToUI( someResults ); // This is what I would LIKE to do
    }
}

Then the client could call startProgram using something like:

return startProgram(42, 12, 20, ^(int someResults) {
           dispatch_async(dispatch_get_main_queue(), ^{
              // Update UI in some way.
           });         
       });

This way your code will have no dependency on what or how the client do and uses the progress callback for. Also it is nice dependency injection.

If using blocks is not possible (model code might need to be pure C to work on other platforms?) then you can switch the block for a function pointer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文