简体   繁体   English

来自 C++ 的 Swift Bridging 标头不起作用

[英]Swift Bridging header from C++ is not Working

My need was that I want to call a swift function from my cpp code.我的需要是我想从我的 cpp 代码中调用一个 swift 函数。 I have tried Using Bridging method for this purpose.为此,我尝试过使用桥接方法。 When I try to call a swift from c it is working.当我尝试从 c 调用 swift 时,它正在工作。 Since C and C++ are similar, I used the same logic in C++ ,but it is not working.由于 C 和 C++ 相似,我在 C++ 中使用了相同的逻辑,但它不起作用。

Compilation of this CPP code gives error like Undefined symbol: sayHello() .编译此 CPP 代码会产生类似Undefined symbol: sayHello() 的错误。

My c and c++ sample code is like this ,我的 c 和 c++ 示例代码是这样的,

CToSwift-Bridging-Header.h CToSwift-Bridging-Header.h

void callCpp();

extern void sayHello();

main.c/.cpp main.c/.cpp

#include <stdio.h>
#include "CToSwift-Bridging-Header.h"

int main(int argc, const char * argv[]) {
    printf("Hello, Main!\n");
    callCpp();
    return 0;
}

void callCpp() {
   printf("CPP: Hi This is C\n");
    printf("CPP: Swift say hello to everyone !\n");
    sayHello();
    printf("CPP: Nice! ");

}

Testswift.swift Testswift.swift

import Foundation

    @_cdecl("sayHello")  
    func sayHello()
    {
        print ("Swift:Hello , Welcome to Swift")
    }

After reading some available documentation for this concept, I understand Swift (Obj c) and C++ is not directly related since both are evolved from C on different manner.在阅读了一些关于这个概念的可用文档后,我明白 Swift (Obj c) 和 C++ 没有直接关系,因为两者都是从 C 以不同的方式演变而来的。

But my queries are但我的疑问是

1] Is something else which I am missing in this Bridging header method to call a swift function from a C++ Code? 1] 在这个桥接头方法中我还缺少从 C++ 代码调用 swift 函数的其他东西吗?

2] Is there any other Method to achieve my goal ? 2] 还有其他方法可以实现我的目标吗?

3] Can we able to pass the swift code as a library or dll when compiling C++ ? 3] 我们可以在编译 C++ 时将 swift 代码作为库或 dll 传递吗?

This looks like a name mangling issue.这看起来像是名称修改问题。

C++ adds information to the name of each function that encodes the parameter and return types so that overloading with different parameter types works. C++ 将信息添加到对参数和返回类型进行编码的每个函数的名称中,以便使用不同的参数类型进行重载。

The normal trick to include C headers (which your bridging header is effectively) is an extern "C" { ... } If I remember correctly from my C++ programming days 20 years ago, it should go like this:包含 C 头文件(您的桥接头文件有效)的正常技巧是extern "C" { ... }如果我从 20 年前的 C++ 编程天没记错的话,它应该是这样的:

#ifdef __cplusplus

void callCpp();

extern "C" {
#endif

extern void sayHello();

#ifdef __cplusplus
}
#endif

Everything inside the extern "C" { ... } will be treated by the C++ compiler as straight C and so no name mangling will be done. extern "C" { ... }都将被 C++ 编译器视为纯 C,因此不会进行名称修改。 The compiler will remember this if it encounters the function implementation inside C++ code and will apply no name mangling to it either so the extern declaration and the implementation have matching names.如果编译器遇到 C++ 代码中的函数实现,编译器将记住这一点,并且不会对其应用名称修改,因此 extern 声明和实现具有匹配的名称。

The ifdef s stop C (and Swift) from seeing the C++ extern "C" { ... } . ifdef s 阻止 C(和 Swift)看到 C++ extern "C" { ... }

On the assumption that you want callCpp() to use C++ conventions, I've put it outside the extern "C" but inside the ifdef so it is not visible to C and Swift programs.假设您希望callCpp()使用 C++ 约定,我将它放在extern "C"但在ifdef内,因此它对 C 和 Swift 程序不可见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM