如何在 Haxe 中使用 C/C++ 库(如 NCurses)

How to use a C/C++ library (like NCurses) in Haxe

我有一个用 Haxe 编写并通过 C++ (hxcpp) 编译为二进制文件的 cli。我想在其中使用 ncurses。我在 C 中使用过 ncurses,在 Haxe 中使用过 JS externs,但我无法弄清楚 Haxe/C++ 文档将两者联系在一起。

除了基本的 haxe 命令(即不构建文件等),我没有使用更多的 HXCPP 编译器,à la:

haxe -lib somelib -cp src --cpp bin/cpp path.to.Main

基本上,我可以使用所有自定义代码,但在外部代码上遇到困难。所以我不完全确定我在实现目标方面还缺少多少步骤。但我可以看到一些主要障碍。

  1. 如何在构建中包含 ncurses? IE。 cc -lncurses -o out [etc...] 在 Makefile 中。
  2. 如何包含正确的 extern 以允许 Haxe 完全无错误地编译。我看到的所有外部示例都涉及 class/namespace,但 NCurses 函数没有 class 或名称空间。我还没有找到关于裸外部函数的任何文档。
  3. 然后当然是在我实际的 Haxe 代码中正确包含 headers(或等效的 haxe 编译)的基础知识。

我知道这基本上是在要求 mini-tutorial,但我找不到可以放在一起实现此特定目标的示例或文档。

感谢您提供的任何帮助。

HXCPP 使用 xml-based build system。当您启动时 haxe -cp src --cpp bin/cpp path.to.Main:

  1. Haxe 文件被转译为 C++,并在输出目录中生成 Build.xml,即 bin/cpp/Build.xml
  2. 一切都由 HXCPP 构建,将新生成的项目 Build.xmlglobal default xml definitions 合并,然后调用编译器工具链。

您可以通过 @:buildXml 元数据 as described on the manual 将编译器标志、库注入 link、includes 目录等:

@:buildXml("
    <target id='haxe'>
       <lib name='-lncurses' if='linux'/>
       <lib name='ncurses.lib' if='windows'/>
    </target>
")
class Main{ ... 

这些标签将附加到项目 Build.xmlThe haxe target is the default target. Keep in mind that every toolchain (MSVC, gcc, Xcode, etc.) has its own syntax. You can see examples in the build.xml of cross-platform low-level projects like Systools or Lime.

可以在haxe命令行中加入-D HXCPP_VERBOSE查看实际启动了哪些命令:haxe -D HXCPP_VERBOSE -cp src --cpp bin/cpp path.to.Main.

至于外部人员,更简单的情况是:

  1. 您在 @:cppFileCode() 块中使用#includes 和所需的一切编写 C++ 代码;你在这里写的所有内容都会粘贴到生成的 cpp 文件中 as-is;
  2. 您将在其中一个 haxe 类 上定义的一个 haxe 函数标记为 @:native("nameOfTheCppFunction"),构建系统会将它们连接在一起。
    @:cppFileCode("
        #include <ncurses.h>

        void nativeCppTest(){
             /* here goes your ncurses code */
             return;
        }
    ")

    class Main{
        public static function main()
        {
            myCppTest();
        }

        @:native("nativeCppTest")
        extern static function myCppTest():Void;
    }

如果您打开生成的文件(在本例中为 bin/cpp/src/Main.cpp),您会看到 haxe myCppTest() 调用已更改为其原始版本 nativeCppTest().

如果您想传递函数参数并接收 return 值,则必须将这些 using the cpp.* standard library types 包装起来。例如:

    @:cppFileCode("
        #include <ncurses.h>

        void nativeCppTest(const char* myString){
             /* here goes your ncurses code */
             return;
        }
    ")

    class Main{
        public static function main()
        {
            myCppTest("print this");
        }

        @:native("nativeCppTest")
        extern static function myCppTest(myString:cpp.ConstCharStar):Void;
    }

有些转换是自动的(例如,在本例中,从常量字符串到 ConstCharStar),有些则需要显式 cast;如果你需要传递指向 C++ 代码的指针,你可以通过 cpp.RawConstPointer.addressOf(<haxe object>)(如果不是 const,则为 RawPointer):

    public static function main()
    {
        var myString:String = "print this";
        myCppTest(cast cpp.RawConstPointer.addressOf(myString));
    }

有用的参考资料: