# oh_dotnettool **Repository Path**: lightsever/oh_dotnettool ## Basic Information - **Project Name**: oh_dotnettool - **Description**: 开发一组鸿蒙pc 使用的 命令行工具 使用dotnet gitee.com/lightsever/install-dotnet-harmonyos - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-20 - **Last Updated**: 2026-07-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # oh_dotnettool HarmonyOS .NET 工具集。当前主要内容: - **`oh_tool`** — HarmonyOS 设备连接与调试 CLI - **HAP 模板工作流** — 用 HAP 模板替换 `.so` 实现快速迭代 - **`csharp/logic/`** — C# NativeAOT 示例(编译成 `liblogic.so` 注入 HAP) ## oh_tool 安装 依赖: - .NET 10 SDK - HarmonyOS 真机(已开启网络调试,`persist.hdc.mode == tcp`) - `~/bin` 在 PATH 中 ```bash ./install.sh ``` 脚本做三件事:`dotnet build` → symlink 到 `~/bin/oh_tool` → 检查 PATH。 ## oh_tool 用法 ``` 用法: oh_tool <命令> [参数] 命令: open 打开 URL 或文件(--webview / --webhost 修饰符) view 用浏览器预览文件(open --webview 别名) 支持 .md .markdown .html .htm .cs .js .txt .json .xml + 图片 Markdown: marked.js 渲染 HTML: 原样,相对路径资源一并复制 代码 (.cs .js .json .xml): 内嵌高亮 文本 (.txt):
 包裹
          图片: 居中显示
          Markdown/HTML 自动检测相对引用 (图片/css/js),复制并保持路径

  host    以文件或目录为 webroot 起临时 HTTP 服务器(open --webhost 别名)
          oh_tool host .         浏览当前目录(最常用)
          oh_tool host ./docs    浏览指定目录
          oh_tool host index.html  仅服务单个 HTML 文件
          目录模式: 左侧目录树 + 右侧预览,懒加载子目录

  hap     HAP 操作(详细参数请输入 oh_tool hap)
```

### 常见用法

```bash
# 浏览当前目录(树形 + 预览)
oh_tool host .

# 用浏览器预览 Markdown / 代码 / 图片
oh_tool view README.md
oh_tool view src/Program.cs
oh_tool view docs/diagram.png

# 安装/启动 HAP
oh_tool hap install dist/entry.hap
oh_tool hap run light.hx.dotnet
```

## HAP 模板工作流

### 为什么用模板

HAP 本质是 ZIP,包含 ArkTS 字节码、资源、`libs/*.so`、`module.json` 等。完整构建需要 DevEco Studio 跑完 ArkTS 编译 + 资源编译 + 打包 + 签名,单次 30-60 秒。

如果只改 native(C++/C#),ArkTS 和资源没动,重打整个 HAP 是浪费。**模板替换法**:把 DevEco 构建出的 HAP 作为模板,每次迭代只换里面的 `.so` + 重签,5-10 秒搞定。

```
传统:    改 .cpp → cmake → DevEco 全量构建 → 签名 → 安装     (30-60s)
模板替换: 改 .cpp → cmake → 解 HAP → 换 .so → 打包 → 签名      (5-10s)
```

### 准备模板(一次性)

用 DevEco Studio 构建 `hapsrc/loader/`,把产物复制为模板:

```bash
cp hapsrc/loader/entry/build/default/outputs/default/entry-default-signed.hap \
   hapsrc/loader/dist/template.hap
```

何时需要重建模板:
- 改了 ArkTS 代码 (`*.ets`)
- 改了资源 (`resources/`)
- 改了 `module.json`
- 新增了 `.so` 依赖库

仅改 native 代码 → **不需要重建模板**。

### 用 .NET (NativeAOT) 开发 native

C# 可以通过 NativeAOT 编译成 HarmonyOS 能加载的 `.so`。仓库里的 `csharp/logic/` 是示例。

**1. C# 项目配置**(参考 `csharp/logic/logic.csproj`):

```xml

  
    net10.0
    ohos-arm64
    true
    true
    logic
    Library
  

```

关键点:
- `RuntimeIdentifier` 必须是 `ohos-arm64`(不是 `linux-arm64`,否则会链接到 HarmonyOS 缺失的系统库)
- `PublishAot` 输出 `liblogic.so`(基名取 AssemblyName)

**2. C# 导出 `app_init`,C++ 通过 dlopen+dlsym 调用它并传入 bridge 的查询函数**

`bridge.cpp` 维护一张 host 侧函数表,按名字(UTF-16 + strlen)查函数指针:

```cpp
// bridge.cpp
static void* bridge_get_func_ptr(const char16_t* name, int strlen) {
    u16sv key(name, (size_t)strlen);
    if (key == u"log")                 return (void*)bridge_log_impl;
    if (key == u"gl.get_proc_utf8raw") return (void*)bridge_gl_get_proc_impl;
    if (key == u"asset.open")          return (void*)bridge_asset_open_impl;
    // ...
    return nullptr;
}

static void load_logic(void) {
    void* h = dlopen("liblogic.so", RTLD_NOW | RTLD_LOCAL);
    auto init = (void (*)(OHBridge_GetFuncPtr))dlsym(h, "app_init");
    init(&bridge_get_func_ptr);  // 把 host 查询函数传给 C#
}
```

C# 侧 `app_init` 接收查询函数,缓存需要的 host 接口,然后注册自己的回调(`on_render_frame` 等):

```csharp
// Logic.cs
private static delegate* unmanaged _get;  // bridge_get_func_ptr
private static delegate* unmanaged _log;

[UnmanagedCallersOnly(EntryPoint = "app_init")]
public static void AppInit(delegate* unmanaged get)
{
    _get = get;
    _log = (delegate* unmanaged) Query("log");
    // ... 查 gl.get_proc_utf8raw / asset.* / SetCallback 等

    RegisterCallback("on_render_frame", &OnRenderFrame);
    RegisterCallback("on_shutdown",      &OnShutdown);
}
```

ABI 约定:
- 字符串参数:UTF-16 `char*` + 显式 `strlen`(C# 是 UTF-16,C++ 侧用 `char16_t`)
- 例外:`gl.get_proc_utf8raw` 是原始 UTF-8 `const char*` 不带 strlen,省一次转码
- 回调:C# `[UnmanagedCallersOnly]` 静态方法,通过 bridge 的 `SetCallback(name, ptr)` 注册

详见 [docs/native-bridge-api.md](docs/native-bridge-api.md)。

**3. 编译**:

```bash
dotnet publish csharp/logic -r ohos-arm64 -c Release
# 产物: csharp/logic/bin/Release/net10.0/ohos-arm64/publish/logic.so
```

**4. 注入 HAP**(推荐 `oh_tool hap quickpack`):

写一个 `oh_tool_pack.json` 描述怎么打包:

```json
{
  "output": "hapsrc/loader/dist/quickpack-test.hap",
  "template": "hapsrc/loader/dist/template.hap",
  "sign_config": "sign-config.json",
  "libs": [
    {"src": "hapsrc/loader/entry/src/main/cpp/build/libsurface_provider.so",
     "dst": "libs/arm64-v8a/libsurface_provider.so"},
    {"src": "csharp/logic/bin/Release/net10.0/ohos-arm64/publish/logic.so",
     "dst": "libs/arm64-v8a/liblogic.so"}
  ],
  "resource_dir": "hapsrc/loader/entry/src/main/resources/rawfile"
}
```

签名参数走单独的 JSON(密码不进配置文件):

```json
// sign-config.json
{
  "keystore": "/path/to/keystore.p12",
  "cert":     "/path/to/cert.cer",
  "profile":  "/path/to/profile.p7b",
  "keyAlias": "app_key"
}
```

执行:

```bash
oh_tool hap quickpack -keyPwd 123456 -keystorePwd 123456
```

`quickpack` 自动:解模板 → 替换 `.so` → 注入 rawfile 资源 → 重新打包 → 签名。

**5. 安装测试**:

```bash
oh_tool hap install hapsrc/loader/dist/quickpack-test.hap
oh_tool hap run light.hx.dotnet
```

详见 [docs/hap-workflow/](docs/hap-workflow/)。

## 项目结构

```
oh_dotnettool/
├── src/
│   └── oh_tool/              # oh_tool CLI
│       ├── Program.cs
│       ├── OpenCommands.cs    # open/view/host
│       ├── HapCommands.cs     # hap install/unpack/pack/sign/quickpack/run/info
│       ├── WebHostCommands.cs # HTTP 服务器
│       ├── HtmlResources.cs   # 模板渲染 + 资源扫描
│       └── content/           # HTML 模板(markdown/code/explorer)
├── hapsrc/loader/            # GLES loader HAP(DevEco 项目)
│   ├── entry/src/main/cpp/   # C++ bridge
│   └── dist/template.hap     # HAP 模板
├── csharp/logic/             # C# NativeAOT 示例(产出 liblogic.so)
├── docs/
│   ├── hap-workflow/         # HAP 模板工作流详细文档
│   ├── native-bridge-api.md  # bridge ⇄ logic 函数指针 ABI
│   └── native-bridge-arch.md # 架构
├── install.sh                # oh_tool 安装脚本
└── rebuild-so.sh             # 仓库内快速重编译(quickpack 的前身)
```

## 环境

- 运行:HarmonyOS 真机(HongMeng Kernel 1.12.0)
- hdc:`/data/service/hnp/bin/hdc`
- 签名证书:`/storage/Users/currentUser/Documents/signner/`
- 打包/签名工具:从 `builder_oh` 仓库获取