首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

VS2010 靜態編譯 cJSON 2.1 嵌入 Lua 5.2 完整指南

     編輯:關於C

項目需在 Lua 5.2 中使用 JSON,選擇高性能的 cJSON(C 實現),並將其編譯為靜態庫鏈接進 Lua,避免運行時依賴。本文記錄 VS2010 下的完整編譯步驟與踩坑記錄。

準備工作

  • Lua 5.2 源碼
  • cJSON 2.1 源碼(cJSON.c、cJSON.h、fpconv.c、fpconv.h)
  • VS2010 開發環境

工程結構

lua_static_lib/
├── lua/           # Lua 5.2 源碼
│   ├── src/
│   │   ├── *.c, *.h
│   │   ├── linit.c
│   │   └── lualib.h
├── cjson/         # cJSON 源碼
│   ├── cJSON.c
│   ├── cJSON.h
│   ├── fpconv.c
│   └── fpconv.h
└── lua_static.vcxproj

關鍵修改點

1. Lua 端:註冊 cJSON 模塊

lualib.h 添加聲明:

#define LUA_CJSONLIBNAME  "cjson"
LUAMOD_API int (luaopen_cjson) (lua_State *L);

linit.c 註冊到標準庫列表:

static const luaL_Reg loadedlibs[] = {
    {"_G", luaopen_base},
    {LUA_LOADLIBNAME, luaopen_package},
    {LUA_COLIBNAME, luaopen_coroutine},
    {LUA_TABLIBNAME, luaopen_table},
    {LUA_IOLIBNAME, luaopen_io},
    {LUA_OSLIBNAME, luaopen_os},
    {LUA_STRLIBNAME, luaopen_string},
    {LUA_BITLIBNAME, luaopen_bit32},
    {LUA_MATHLIBNAME, luaopen_math},
    {LUA_CJSONLIBNAME, luaopen_cjson},  // ← 新增
    {LUA_DBLIBNAME, luaopen_debug},
    {NULL, NULL}
};

2. cJSON 端:適配 MSVC

刪除 fpconv.c(MSVC 不支援其內聯語法)

修改 fpconv.h:

#define FPCONV_G_FMT_BUFSIZE  32
#define USE_INTERNAL_FPCONV   // 強制使用內部實現
#define inline __inline       // MSVC 關鍵字

#ifdef USE_INTERNAL_FPCONV
static inline void fpconv_init() { /* 空實現 */ }
#else
extern inline void fpconv_init();
#endif

extern int fpconv_g_fmt(char*, double, int);
extern double fpconv_strtod(const char*, char**);

修改 lua_cjson.c 頭部:

#include "..\lua.h"
#include "..\lauxlib.h"

#include 
#define isnan(x) ((x) != (x))
#define isinf(x) (!_finite(x) && !_isnan(x))
#define strncasecmp _strnicmp

編譯設置

  • 配置屬性 → C/C++ → 預處理器 → 添加 LUA_BUILD_AS_DLL=0(靜態庫)
  • 將 cJSON 所有 .c/.h 加入專案(建議建立「篩選器」管理)
  • 編譯目標:靜態庫 .lib 或直接輸出 .exe

驗證測試

編譯成功後,在 Lua 腳本中即可直接使用:

local json = require("cjson")
local t = {name = "test", value = 123}
local str = json.encode(t)
print(str)  -- {"name":"test","value":123}
local obj = json.decode(str)
print(obj.name)  -- test

常見問題排查

錯誤現象原因解決
unresolved external symbol luaopen_cjsonlinit.c 未註冊或聲明缺失檢查 lualib.h 聲明、linit.c 註冊表
fpconv 相關編譯錯誤MSVC 不支援 GNU inline 語法刪除 fpconv.c、修改 fpconv.h 定義 USE_INTERNAL_FPCONV
isnan/isinf 未定義MSVC 使用 _isnan/_finitelua_cjson.c 宏定義映射
strncasecmp 未定義MSVC 為 _strnicmp宏定義映射

優化建議

  • 將 cJSON 直接編譯進 Lua 靜態庫,僅產出單一 lua52_static.lib
  • 啟用 /O2 優化、/MT 靜態運行時,減少依賴
  • 如需動態庫,修改 LUA_BUILD_AS_DLL=1 並導出符號

結語

將 cJSON 靜態編譯進 Lua,既保證了部署簡單(單一二進制),又獲得了高性能 JSON 解析。關鍵在於處理好 MSVC 與 C99 代碼的兼容性差異。此法同樣適用於其他 C 庫嵌入 Lua 的場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved