编写及编译合约

本文首先通过示例(Hello World)来说明普通 wasm 合约的编写、编译过程,然后简单介绍关于构建静态库的方法。

说明

在编写C++合约时,平台在接口名称的命名上有一些限制,具体可参见接口名称限制说明

普通 wasm 合约

  1. 创建一个临时目录,用于存放编写的合约,例如 /tmp/bob

     mkdir /tmp/bob
     cd /tmp/bob
  2. 创建一个 hello.cpp文件,即合约代码文件。

     touch hello.cpp
  3. 编辑 hello.cpp,引入需要的头文件。

     #include <mychainlib/contract.h>

    mychainlib/contract.h中包含编写合约所需的数据结构和 C++ API。

  4. 使用如下方式编写合约:

    #include <mychainlib/contract.h>
    using namespace mychain;
    
    class hello:public Contract {
    public:
        INTERFACE void hi(const std::string& user ) {
            Log("hi"s, {"ok", user});
        }
    };
    INTERFACE_EXPORT(hello, (hi))
  5. 在完成合约编写后,执行以下命令编译合约:

    说明

    假设合约文件的名称是xxx.cpp,则执行命令my++ -o xxx.wasm xxx.cpp

     my++ -o hello.wasm hello.cpp

    如果命令执行成功,您将在 /tmp/bob目录下看到以下三个文件:

    • hello.wasm:合约的 wasm 字节码文件

    • hello.abi:合约的 ABI 定义文件

    • hello.wasc:合并字节码和 ABI 的文件,在部署合约时,交易中的 code字段就是该文件内容。

      执行编译命令时,如果使用 -o选项指定的文件名不是以 .wasm 结尾,那么产生的 ABI 文件就是 -o指定的文件名后面直接加 .abi。

      例如,执行编译命令:

      my++ -o abc hello.cpp

      会产生名为 abc.wasc的字节码文件和名为 abc.abi的 ABI 定义文件。

      说明

      ABI文件的格式定义请参见ABI定义

    my++ 也可以同时编译多个源文件。例如您可以在 contract.cpp中定义合约,在 utils.cpp中定义一些工具函数,则编译命令为:

    $ my++ contract.cpp utils.cpp -o contract.wasm

构建静态库

您可以使用 MYCDT 提供的工具,将一组源文件编译打包成一个 wasm 的静态库,提供给合约使用。

例如,您已编写了两个 C++ 源文件 foo.ccbar.cc,并且分别定义了一些工具函数,则函数接口统一声明在头文件 foobar.h中。

├── bar.cc
├── foo.cc
└── foobar.h

用以下命令编译源代码,然后打包成一个静态库 foobar.a

$ my++ -c foo.cc bar.cc
$ llvm-ar rcs foobar.a foo.o bar.o
说明

说明:my++ 可以一次编译单个或多个源文件。

如果您需要在合约内使用这个静态库,只需在合约代码中包含头文件 foobar.h,然后编译合约时指定静态库路径即可。

$ my++ main.cc /path/to/foobar.a -o contract.wasc