UWP中为 WinRT 组件创建 NuGet 包

2026年9月6日 没有评论

这篇文章可以说是迟到了 N 多年的分享了,一直放在草稿箱里但是没有发布,今天赶紧地整理。

先搞清楚:WinRT 组件里到底有什么

假设我们有一个 WinRT 组件:Demo.winmd、Demo.dll。这两个文件虽然经常一起出现,但职责完全不同。.winmdWindows Metadata 文件,它描述的是这个 WinRT 组件对外暴露的类型信息,比如:

namespace
class
interface
method
property
enum

WinRT 的语言投影也依赖这些 metadata。比如 C++/WinRT 会根据 WinRT metadata 生成对应的 C++ 投影代码。所以可以简单理解成:Demo.winmd 告诉编译器“这个组件长什么样”,它本身并不是业务代码的实现。.dll 才是实际的 native implementation。也就是说:Demo.dll 真正执行代码。对于一个典型的 WinRT Component,这两个文件是配套的。

Visual Studio 在构建 Windows Runtime Component 时,会生成 WinRT metadata;对于 C++/WinRT 项目,工具链也是先处理 IDL 生成 .winmd,再基于 metadata 生成相应的投影代码。

不要把 .winmd 理解成普通 .NET 程序集,也不要把它和 DLL 当成两个可以随便替换的文件。它们共同描述并实现了一个 WinRT 组件。

NuGet 包里应该放什么?

对于这个例子,一个最基本的 NuGet 包可以长这样:

com.xx.demo.nupkg
│
├─ lib
│  └─ uap10.0
│     └─ Demo.winmd
├─ runtimes
│  ├─ win10-x86
│  │  └─ native
│  │     └─ Demo.dll
│  └─ win10-x64
│     └─ native
│        └─ Demo.dll
└─ build
   └─ native
      └─ com.xx.demo.targets

这里其实就是整个事情最关键的部分,.nuspec 本身反而没什么好讲的——如果你平时用 NuGet,知道怎么写一个基本的 .nuspec 就够了。

为什么 .winmd.dll 要放在不同目录?

这是很多第一次做 native NuGet 包的人容易疑惑的地方。.winmd 是给编译阶段使用的,所以我们把它放到 lib/uap10.0/,而 DLL 属于 native runtime binary,因此放到:runtimes/win10-x64/native/、runtimes/win10-x86/native/。

这样做的一个直接好处就是:同一个 NuGet 包可以同时支持多个 CPU 架构。微软的 UWP NuGet 示例也是把 WinMD 放到 lib\uap10.0,native DLL 放到 runtimes 对应的架构目录。 Microsoft Learn+1

C++ 项目为什么还需要 .targets

NuGet 对 native C++ 包的处理方式,本身就和 .NET 程序集不太一样。微软的 native NuGet 文档也明确提到,native 包通常通过 buildcontenttools 等目录以及 MSBuild 的 .props/.targets 来完成项目集成,而不是依赖 lib 直接添加 C++ Reference。 所以我们通常需要提供一个:com.xx.demo.targets。它的作用可以简单理解成:告诉 MSBuild:这个 NuGet 包里的 WinMD 和 DLL 怎么添加到当前项目。

一个简化后的思路大概是:

<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'UAP'">
    <Reference Include="
        $(MSBuildThisFileDirectory)
        ..\..\lib\uap10.0\Demo.winmd">

        <Implementation>Demo.dll</Implementation>
    </Reference>
    <ReferenceCopyLocalPaths Include="
        $(MSBuildThisFileDirectory)
        ..\..\runtimes\win10-$(Platform)\native\Demo.dll" />
</ItemGroup>

.nuspec 不需要写得很复杂

如果已经熟悉 NuGet,可以把它理解成一个文件映射:

<files>
    <file
        src=".\Demo.winmd"
        target="lib\uap10.0" />
    <file
        src=".\Demo.dll"
        target="runtimes\win10-x64\native" />
    <file
        src=".\com.xx.demo.targets"
        target="build\native" />
</files>

如果还要支持 x86,就再放一个对应的 DLL:runtimes/win10-x86/native/Demo.dll。

这里最重要的不是 XML 本身,而是记住:

WinMD
    → lib/uap10.0
Native DLL
    → runtimes/<RID>/native
MSBuild 集成
    → build/native

XML 文档要不要一起打包?

如果组件是给别人使用的,比较建议加上。里面保存 C++/C# 的 API 文档注释,这样 IDE 可以显示对应的 API 注释。这个东西不影响组件运行,但对 SDK 类组件来说体验差别还是挺大的。

分类: 日常 标签: ,

如何找到适合自己的 llama.cpp 配置

2026年8月28日 没有评论

众所周知,llama.cpp 是一个使用 C++ 来实现的一个大模型推理工具,不依赖 python, pytorch,而且性能也很好,支持自定义的参数调整。Ollama 底层也是封装了这个库,提供给普通用户。

Ollama 的设置对于 AI生成代码这样的专业场景下,不一定可以发挥硬件的最大性能,所以有的场景,还是会有人直接使用 llama.cpp 来加载模型。

对于 Windows 平台,最直接的方式就是使用 winget 来安装:

winget install llama.cpp

今天的这边文章,要和大家分享的是普通的开发人员,如何简单快速地在本地使用 llama.cpp 搭建起本地模型。当然,不可否认,Ollama 依然是很优秀的工具,它们是相互补充而不是替代其中的某一个。

第一步从 HF 上下载 GGUF 模型文件,一般而言大家可以下载 Q4_K_M 格式的文件。

第二步,运行最基础的命令:llama-server.exe -m .\Qwen3.8-27B-UD-Q4_K_M.gguf -ngl 0 -fa off –spec-type none -c 1024,记得模型名称换成你本地实际的模型,先保证你机器可以跑起来,如果你模型不适用你电脑,那么初始化就会报错。

第三步,当可以运行后,你就可以访问 localhost:8080 访问 llama.cpp 提供的简单网页版聊天工具,随便说点什么,在里面你会看到生成的 token 速度,Qwen3.8 在我机器上只有 2t/s,够慢的了。

第四步,结束并运行新的命令:llama-server.exe -m .\Qwen3.8-27B-UD-Q4_K_M.gguf -ngl 10 -fa off –spec-type none -c 1024,可以看到变化是 ngl 从 0 变到了 10,你就可以观察内存和显存的占用情况,如果允许没有问题,就以步长 10,逐步添加,同时也增加 -c 上下文长度。

第五步,打开 mtp,执行下面的命令 llama-server.exe -m .\Qwen3.8-27B-UD-Q4_K_M.gguf -ngl 20 -fa on –spec-type draft-mtp -c 1024, 可以看开启 mtp 后,是否可以初始化成功,一般而言启用了 mtp ,生成 token 的速度会增加,如果你发现没有效果,应该及时关闭,否则得不偿失。

对于我的机器,最后停留在 llama-server.exe -m .\Qwen3.8-27B-UD-Q4_K_M.gguf -ngl 10 -fa on –spec-type draft-mtp -c 32768 这个参数上面。

大家可以自己试一试,没有最好的,只有合适的。

分类: AI, 工具, 日常 标签:

OpenCode 介绍

2026年7月19日 没有评论

OpenCode 是什么?

一句话来说:一个开源的 AI Coding Agent,可以运行在 Terminal、Desktop、IDE 中,并支持几乎所有主流的大模型。相比很多只能调用固定模型的工具,OpenCode 最大的特点就是Provider 无关

基本可以理解成:只要模型提供 OpenAI Compatible API,大概率都能接。

官网地址是 https://opencode.ai,官方也提供桌面版应用,非常适合我这样无法接受命令行的小白。

为什么很多人开始用 OpenCode?如果只看能力,其实现在 AI Coding Agent 都差不多:

  • 修改代码
  • 自动搜索项目
  • 调用终端
  • Git 操作
  • 修 Bug
  • 写测试

这些大家都会。OpenCode 真正吸引人的地方主要有几个:

1. 开源。这是很多人首先关注的一点。整个 Agent 都是开源的,很多时候你甚至可以直接看看它到底是怎么组织 Prompt、怎么管理 Context、怎么调 Tool 的。对于喜欢研究 Agent Workflow 的人,这一点很有价值。

2. 不绑定任何模型。这一点比想象中重要。如果工具绑定 Provider,你只能等官方适配,OpenCode 基本没有这个问题,换模型基本就是改配置。

3. 真正以 Terminal 为中心。很多 IDE 插件,本质还是聊天窗口。OpenCode 更像一个真正工作的 Agent。

例如:修复所有 eslint 错误。它可能会:

  • 搜索项目
  • 分析错误
  • 修改多个文件
  • 执行 npm run lint
  • 再继续修改
  • 最终提交修改

整个过程基本不用你手动介入。这种体验和 Cursor 的 Agent Mode 很接近。

4. LSP 支持。很多 Agent 修改代码其实都是:全文件读取 → LLM 自己猜。OpenCode 会利用 Language Server 获取:

  • Definition
  • Reference
  • Symbol
  • 类型信息

因此:跨文件修改准确率会高不少,尤其大型项目比较明显。

配置建议

项目级 Prompt

很多人一直在聊天。其实更推荐写:AGENTS.md 或者项目 Prompt。

告诉 Agent:项目规范、命名规则、Commit 风格、是否允许执行命令、是否自动运行测试,效果会明显好很多。

自定义命令

OpenCode 支持自定义 Command。

例如:/review,实际上就是:

Review 当前改动,只关注:
- Bug
- 性能
- 安全

以后一句:/review,不用重复输入 Prompt。长期下来效率提升非常明显。

AI 编程工具最大的变化,不是模型越来越强,而是 Agent 越来越成熟。OpenCode 代表的是另一种思路:不是把 AI 塞进 IDE,而是把 AI 放到开发流程本身。它知道你的项目、能调用工具、能执行命令、能管理上下文,也能完成完整的开发任务。

如果你平时就是终端重度用户,或者已经习惯 Claude Code、Aider、Codex CLI 这一类工具,那么 OpenCode 值得体验一下。它未必会成为你的唯一工具,但很可能会成为工具箱里长期保留的那一个。

分类: AI, 日常 标签:

Hermes 配置

2026年6月26日 没有评论

最近 Hermes 的风头又和 OpenClaw 差不多了,于是就下载安装了试一试。我网上找的是是非官方文档地址:https://hermes-agent.org/zh/,按照 GitHub 里的描述也很简单,可惜目前对于 Windows 的支持还处于初级阶段,就在 WSL 里安装了。

和 OpenClaw 一样,安装后按照提示一步步的配置就可以了。这里有碰到一个坑就是,输入模型的 key时,由于输入不可见,导致我粘贴了2次,最后怎么调用都没有成功。

这里记录2个技巧:

~/.env 文件,添加下面的配置,就可以在其它 LLM 聊天app 里,添加 Hermes 作为大模型进行对话,API_SERVER_KEY 就是用于对话 API 调用时需要用到的授权信息。
API_SERVER_ENABLED=true
API_SERVER_KEY=sk-local
API_SERVER_HOST=0.0.0.0
API_SERVER_PORT=10086

取消 GATEWAY_ALLOW_ALL_USERS 的注释,并设置为 true。

我个人理解,使用起来比 OpenClaw 要容易的多,就是青绿色的背景看着有些不适应,其它就还好。直接使用 Hermes dashboard 就可以启动网页版界面了。

分类: AI 标签:

自媒体的一天

2026年5月1日 没有评论

这不是前几天某家厂商推出了新的生图模型出来了嘛,说是效果很好,我就网上各种搜索,拿着新模型生成的图片,上周末就导入到视频处理软件里一段操作,加特效、转场,添加字幕和背景音乐,一顿处理下来,上传了后还很是开心,寻思可以分享给大家看了,不是蛮好的嘛。

结果无意间发现视频被限制了,根本就没有推,我说怎么 0 播放呢,咱也不知道具体什么原因呀,估计是哪里不满足要求,就各种调,再上传,发现都没有效果,仍然被限制了。

一气之下就气了一下,随手就发了几句话搞了个图文。

没有想到,一天之后,那个随手发的文字,居然有 11.4w+ 的播放量,评论也快小一千了,把我给看蒙了,所以说流量这东西,就很奇怪。

第二天,已经 14.5w+ 了,不过可以明显感觉到流量推广的下降。

到第三天,数据是 24w+ 了。

写在这里,留作纪念。

分类: 自媒体 标签: ,

Manim 的安装和使用

2026年4月1日 没有评论

最近看到短视频里有很多教学演示动画,就留意了下,于是就发现了 Manim 这个强大的工具。

Manim 是一个强大的动画引擎,专为数学和科学可视化设计,能够生成高质量的数学动画,并广泛用于创建教育视频。

Manim 的安装,使用 uv 的虚拟环境:

uv pip install manim

此外,manim 一般还依赖 MiKTeX ,以方便的在动画里展示公式等非简单文本信息。

Manim 的核心概念

  • 场景(Scene)模块:一个场景可以看作是一个动画的舞台,在这个舞台上可以添加各种数学对象和动画效果。例如,用户可以创建一个名为“勾股定理”的场景,在这个场景中展示线性变换的动画。
  • 对象(Object)模块:Manim中有各种各样的数学对象,如点(Dot)、线(Line)、多边形(Polygon)、函数图像(Graph)等。这些对象可以被添加到场景中,并通过动画来展示它们的变化。以函数图像为例,用户可以定义一个函数(y = x^{2}),然后将其函数图像作为一个对象添加到场景中,随后通过动画来展示函数图像随着参数变化而产生的平移、伸缩等变化。
  • 动画(Animation)模块:这个模块负责实现各种动画效果。常见的动画效果包括移动(MoveTo)、旋转(Rotate)、缩放(Scale)等。例如,用户可以创建一个动画,让一个点从坐标((-1,0))移动到((5,5)),或者让一个几何图形围绕某个中心点旋转一定的角度。

AI 生成的演示脚本里,可能无法直接看到视频,就可以用下面的命令,显示地生成动画:

manim -qh --fps 60 .\演示.py Demo

这样就会在演示.py 所在目录的 media\videos\演示\1920p30 目录下,生成 Demo.mp4 文件,注意对比命令里的参数和文件夹路径之间的关系。

分类: AI, 工具 标签:

解决 Supabase IPv4 连接问题

2026年3月3日 没有评论

其实在上个月的时候就发现,办公网络环境下,无法连接到我的 Supabase 数据库实例上,当然在家里的网络就没有这个问题,一直以为是 IT 给屏蔽了,但是心里总是不明白 IT 为啥要这么做。

今天无意间ping 了下分配的域名,发现只能解析到 IPV6 地址,才意识到这是典型的IPv4/IPv6网络兼容性问题。

经过检索,这篇帖子提供了线索,到 Supabase 的官网上一看,果然人家说的很清楚,当时自己没有留意。

迅速从默认的 Direct 连接切换到 Transaction pooler,就没有问题了。虽然牺牲了一些性能,但是好歹是可以使用了。

最后提醒一下,这两种连接方式,需要用到的用户名是不一样的,密码是一样的。

分类: 日常 标签:

ubuntu 18.04 升级gcc

2026年2月10日 没有评论

要在Ubuntu 18.04 上升级g++到版本10,可以按照以下步骤进行操作:

  1. 打开终端。
  2. 更新系统软件包列表,使用命令sudo apt update
  3. 安装必需的依赖项,使用命令sudo apt install build-essential。这将确保所有构建工具都已正确安装。
  4. 添加PPA(Personal Package Archive)存储库来获取最新的GCC编译器版本。运行以下命令:sudo add-apt-repository ppa:ubuntu-toolchain-r/testsudo apt update
  5. 安装GCC 10及其相关组件,使用命令sudo apt install gcc-10 g++-10
  6. 设置默认的C++编译器为GCC 10,使用命令sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100sudo update-alternatives --set gcc /usr/bin/gcc-10。同样地,也可以通过类似的方式设置默认的C编译器。
  7. 现在,您应该能够使用GCC 10进行编程了。

注意:由于Ubuntu 18.04不支持直接从官方源中提供GCC 10,因此我们使用第三方PPA存储库来获得最新版本。

sudo update-alternatives –install /usr/bin/g++ g++ /usr/bin/g++-8 100

为什么在现在还在说一个版本这么旧的话题?是因为一些 armv7 的设备,还运行的是老版本,而且由于华强北自定义的镜像,只能停留在那个版本的系统。有时候感觉就很可惜。
分类: 日常 标签:

代码行数统计工具

2026年1月19日 没有评论

每当一段时间过,就会有触发需求,统计大家的代码量、UT 覆盖率之类的。经过一番搜索,找到了 cloc 这个今天想要推荐的工具,其开源地址为:https://github.com/AlDanial/cloc

这个工具可以按语言类型、单文件或文件夹、空白行数之类的来过滤,使用也很简单,下载到本地后就是一个单绿色程序,对于 Linux 和 Mac 系统也支持。

随着现在 CI/CD 的集成,代码统计在云端也都有了,但是本地放一个,某些场景下就会派上用处。兄弟,你信我没错的。

大家可以基于我的模板来改吧改吧。

cloc.exe c:\code\project\ --include-lang="C,C++,C/C++ Header,CSS,HTML,Java,JavaScript,JSX,Kotlin,Objective-C,Objective-C++,Swift,TypeScript,JSON,Markdown"

最后,祝大家好运。

分类: 一句话, 日常 标签:

驱动快速备份和还原

2025年12月5日 没有评论

最近在写 PPT 时电脑挂了,虽然马上就换了个备用机器,但是发现了一个问题就是缺少打印机驱动。

以前的硬盘虽然可以作为移动硬盘使用,但是很显然,驱动是无法直接拷贝的。

那个打印机驱动实在是过于久远,系统无法识别出来,默认的驱动包而且还会安装额外的应用,对于有洁癖的人来说,有点不能忍受。

经过一番检索,一个合适的步骤如下:

1,网上搜索打印机对应的驱动安装包,在测试机器上安装。
2,测试机查看打印机设备的驱动,记住它的驱动文件名名称,例如 printxxx.inf
3,测试机上导出驱动,
dism /online /export-driver /destination:”C:\Users\xxx\Desktop\backup”
4,进入这个文件夹,里面会有很多子文件夹。根据第二步里的文件名,搜索相关的子文件夹
5,这个子文件夹,就是驱动实际会用到的最小集合。拷贝到目标机器上。
6,目标机器上,选择添加打印机,然后手动浏览驱动,选择刚才拷贝的子文件夹
7,无脑下一步,就会发现打印机被添加上了
8,备份这个驱动文件夹。以后再添加打印机时,就可以跳过前面5步,直接开始手动添加驱动了

上面的方式,可以满足基本的打印需求。如果是要支持扫描之类的功能,那还是安装默认的全家桶吧。

理论上,也支持其他类型的驱动。

分类: Windows, 日常 标签: