1.12. 开发项目:LAS-CORE 测井数据解析库

1.12.1. 项目简介

LAS-CORE 是一个从零编写的、仅依赖标准 C 运行库的 LAS 文件格式解析库, 用于解析测井行业通用的 Log ASCII Standard(LAS 2.0 / 3.0)数据文件。

项目与 XTF-CORE 采用**同一套工程约定**(C89/C90、 make / CMake 双轨、零全局状态、GPL-3.0),在核心库之上同样提供 Fortran 2003 / Python 3 / C# .NET 3.5 / Lua 5.x 四套语言绑定, 是 C 语言「解析器 + 命令行工具 + 多语言绑定」综合项目的又一个完整范例。

项目属性

说明

项目名称

LAS-CORE

项目定位

LAS 2.0 / 3.0 测井数据文件(Log ASCII Standard)解析 / 生成库

语言标准

纯 C(C89/C90 / ANSI C),兼容 VC10

依赖

零第三方库,无 C++ 特性

许可证

GNU GPL v3.0

代码规模

约 4,900 行(核心 4 模块 + C ABI 桥接层 + 4 种语言绑定 + 测试)

备注

LAS-CORE 与 XTF-CORE 的关系:两者都是测井数据解析库, 但**文件格式不同**——XTF 是 ECLIPS 5700 系统的二进制格式, LAS 是 CWLS 发布的行业标准文本交换格式。LAS-CORE 从 XTF-CORE 复用工程基线(目录结构、测试框架、语言绑定方案),并额外支持 Lua 5.x 绑定与 2.0 <-> 3.0 双向版本转换。

1.12.2. 技术栈与设计约束

1.12.2.1. 核心技术

  • 语言:纯 C89/C90,严格兼容 Microsoft Visual C++ 2010(VC10) (无 // 注释、无混合声明、无 long long、无变长数组、无 stdint.h; 整型自行 typedef 为 las_i8/u8/i16/u16/i32/u32,MSVC 下映射 __int8/16/32)。

  • 构建系统:Makefile 与 CMake 双轨并行,产物一致。

  • 编译门槛:gcc -std=c89 -pedantic -Wall -Wextra 零告警为提交门槛。

  • 产物:静态库 liblas.a、共享库 bin/las.dll,另有 Lua 模块 bin/las_lua.dll``(静态链接核心库)与命令行示例 ``lasinfo。

备注

LAS-CORE 是本 DOCS 中 C 语言基础 章节的又一个**实战项目**: 与 XTF-CORE 同属「解析器 + 命令行工具 + 多语言绑定」范式, 但针对的是**文本格式**——文本解析无需字节序处理,核心难度在 节头 / 助记符 / 分隔符的**容错**与 WRAP 换行的重建。

1.12.2.2. 工程规范(硬性约定)

  • 无全局可变状态:一切状态封装在句柄结构体(LasFile)内,通过指针传递。

  • 公共接口最小化:公共头 include/las.h 只暴露只读数据结构与不透明句柄; 内部布局定义在私有头 src/las_internal.h。

  • 统一错误处理:所有函数返回 LasError 枚举,配合 las_error_str() 转可读文本; 禁止裸 exit();新增错误码**追加**到枚举末尾,避免数值漂移。

  • 字符串边界检查:字符串复制使用 las_copy_seg,避免 strcpy 溢出。

  • 每个公开 API 函数都有单元测试:核心 tests/test_las.c 共 180 项断言, 桥接层 tests/test_bridge.c 共 106 项,全部通过。

1.12.3. 系统架构

1.12.3.1. 目录结构

include/las.h         公共接口(只读数据 + 不透明句柄 + 函数原型)
src/las_internal.h    内部结构体(不对外暴露)
src/las_util.c        行裁剪、大小写不敏感比较、数值扫描、~Curve 行解析
src/las_core.c        读 LAS:las_open/las_close、节解析、数据累积
src/las_access.c      读 LAS:信息访问、按名称查找、按列读数据
src/las_write.c       写 LAS:las_export_version(2.0/3.0)
src/api/              语言绑定(统一 C ABI 桥接层)
  las_bridge.{c,h}    C ABI 桥接层(LasHandle = void*)
  fortran2003/        Fortran 2003 绑定(bind(C))+ 测试
  python3/            Python 3 绑定(ctypes)+ 测试
  dotnet/             C# .NET 3.5 绑定(P/Invoke)+ 测试
  lua/                Lua 5.x 绑定(las_lua.c)+ 测试
  build_all.sh        一键构建并运行四种语言测试
tests/test_las.c      单元测试(180 项断言)
tests/test_bridge.c   C ABI 桥接层单元测试(106 项断言)
examples/lasinfo.c    命令行示例(读 LAS / 打印信息 / 导出转换)
LAS/                  LAS 2.0 / 3.0 样例数据文件(只读)
docs/                 格式规范 + 开发文档
bin/ work/            构建产物与测试工作目录

1.12.3.2. 分层设计

┌─────────────────────────────────────────────────────┐
│  语言绑定层  Fortran / Python / C# / Lua 5.x         │
├─────────────────────────────────────────────────────┤
│  C ABI 桥接层  src/api/las_bridge.c(句柄 void*)     │
├─────────────────────────────────────────────────────┤
│  核心实现层  src/*.c(4 个模块,C89 零依赖)          │
├─────────────────────────────────────────────────────┤
│  公共接口层  include/las.h(不透明句柄 + 只读结构体)  │
└─────────────────────────────────────────────────────┘

1.12.4. 核心功能

1.12.4.1. 读 LAS(las_core / las_access)

  • 入口 las_open:自动识别 LAS 2.0 / 3.0 版本;

  • 解析 ~Version / ~Well / ~Curve / ~Parameter / ~A 五类节;

  • 容错解析:节头兼容完整名(~Curve)与单字母缩写(~C),大小写不敏感; 助记符兼容点分(DEPT.M)与空格分隔(GR GAPI);数据兼容逗号/空白分隔, WRAP YES/NO 均按 token 数重建采样行;

  • las_read_curve 按列读取数据,NULL 占位值(如 -999.25)原样保留。

1.12.4.2. 导出与版本转换(las_write)

  • las_export_version(las, out, 2|3) 将已解析内容按目标版本重新导出, 实现 LAS 2.0 <-> 3.0 双向转换;

  • las_export 等价于导出为 2.0。

1.12.4.3. 语言绑定(src/api)

在核心库之上提供**统一 C ABI 桥接层**,供四种语言调用共享库 bin/las.dll:

语言

绑定方式

测试

Fortran 2003

bind(C) 接口模块(las_interface.f90)

46 项断言

Python 3

ctypes.CDLL,提供 LasFile 便捷类

42 项断言

C# .NET 3.5

[DllImport] P/Invoke(LasApi.cs)

40 项断言

Lua 5.x

Lua C 模块(las_lua.c,luaopen_las 导出)

45 项断言

小技巧

Lua 绑定是 LAS-CORE 相对 XTF-CORE 的增量,值得单独说明: las_lua.c 直接以 C 模块编译为 bin/las_lua.dll, 错误以 Lua error 抛出 { code, msg } 表,可用 pcall 捕获; 系统无 Lua 时构建脚本会自动下载源码自举到 bin/lua54/。

1.12.4.4. 示例工具

lasinfo 文件.las [输出.las [2|3]]   # 读 LAS 打印信息;给输出则按版本导出

1.12.5. LAS 格式要点

格式规范见 docs/LAS_FORMAT.md,要点速记:

  • LAS 是「节式」**文本**文件,节头以 ~ 起始;必需节为 ~Version / ~Well / ~Curve / ~A,可选 ~Parameter / ~Other。

  • ~Version:VERS. 版本号(2.0 / 3.0,必须)、WRAP. 换行方式。

  • ~Curve 每行定义一列:MNEM.UNIT : DESC;LAS 2.0 助记符 4 字符, LAS 3.0 最长 8 字符。

  • ~A 逐采样行排列,每行 curve_count 个值(深度 + 各曲线值), 逗号或空白分隔;WRAP YES 时一个采样行可跨多个物理行。

  • 解析策略:按 token 流累积,每 curve_count 个 token 构成一行, 与物理行边界无关,从而天然支持 WRAP YES/NO。

  • NULL 占位值(如 -999.25)原样保留;曲线数据按「行主序」存储: data[row * curve_count + col]。

  • 文本格式**无字节序问题**,数值一律经 strtod / atof 解析; 文件可有 UTF-8 BOM,行结束符兼容 \n 与 \r\n。

1.12.6. 开发记录

项目于 2026-08-10 完成「核心解析库 → 语言绑定层」的完整交付, git 单次提交 18ed3ab,共 37 文件、+7578 行;CHANGELOG 分两个里程碑:

里程碑

内容

0.1.0(核心解析库)

las_open / 节解析 / 容错 / 数据访问 / las_export_version 导出 / test_las.c 180 断言 / lasinfo / 样例数据 / 文档

0.2.0(语言绑定层)

统一 C ABI 桥接层、Fortran / Python / C# / Lua 四套绑定及测试 (46 / 42 / 40 / 45 断言)、test_bridge.c 106 断言、 las_shared 共享库、build_all.sh 一键脚本

1.12.6.1. 工程实践要点

  • 复用 XTF-CORE 工程基线:目录结构、测试框架、语言绑定方案直接沿用, 新项目只聚焦「LAS 文本格式」本身的差异,大幅降低工程成本。

  • 容错优先:节头 / 助记符 / 分隔的多种写法一律容忍,优先保证「能读出真实数据」。

  • 测试先行:每个公开 API 函数均有断言(含错误路径); 断言数由 179 更正为 180(实测计数),数据以实测为准。

  • 工具链踩坑:本机 gfortran 损坏(trivial 程序也静默退出 1), Fortran 绑定必须用 flang-new;PATH 上的 python3 是 Microsoft Store 存根, 各测试脚本自动探测 clang64 的 python;MSYS 环境丢弃系统 TMP, 构建脚本在仓库内自建 .build_tmp;无 Lua 环境时自动下载源码自举。

1.12.7. 构建与测试

# 方式一:make
make            # 编译 liblas.a + 测试 + 示例
make test       # 运行核心单元测试(180 断言)
make test_all   # 核心 + 桥接层(106 断言)

# 方式二:CMake(产物输出 bin/,CTest 在 work/ 运行)
cmake -S . -B build
cmake --build build
cmake --build build --target las_shared   # 共享库 bin/las.dll
ctest --test-dir build

# 语言绑定(先构建共享库,一键跑四种语言测试)
sh src/api/build_all.sh

1.12.8. 快速使用

读取 LAS 并按名称读取一条曲线,再转为 3.0 导出
#include "las.h"

LasFile *las = 0;
LasError e = las_open("LAS/sample20.las", &las);
if (e != LAS_OK) {
    fprintf(stderr, "open failed: %s\n", las_error_str(e));
    return 1;
}

printf("版本: %.1f  曲线: %d  采样: %d\n",
       las_version(las), las_curve_count(las), las_sample_count(las));

int idx = las_curve_index_by_name(las, "GR");   /* 按名称查索引 */
long n = las_sample_count(las);
float *buf = (float *)malloc((size_t)n * sizeof(float));
long got = las_read_curve(las, idx, 0, n, buf);

printf("%s: %.4f ...\n", las_curve_name(las, idx), buf[0]);

FILE *out = fopen("out.las", "wb");
las_export_version(las, out, LAS_VERSION_3);     /* 转 LAS 3.0 */
fclose(out);

las_close(las);

1.12.9. 相关链接

  • 仓库:D:\HJR\LAS-CORE

  • 格式规范:docs/LAS_FORMAT.md

  • 开发文档:docs/DEVELOPMENT.md

  • 变更日志:CHANGELOG.md

  • 样例数据:LAS/sample20.las,LAS 2.0;LAS/sample30.las,LAS 3.0(WRAP YES)

  • 姊妹项目:XTF-CORE,ECLIPS 5700 二进制格式解析库