PostgreSQL 16 中文分词插件 zhparser 在 Windows 11 上的编译与安装

0 阅读6分钟

前言:

近期在学习过程中,需为 Windows 11 环境下的 PostgreSQL 16 配置中文分词功能,核心依赖 zhparser 插件。然而,网上现存教程多为多年前的旧版本适配方案,与 PostgreSQL 16 + Windows 11 的新环境存在兼容性差异,可参考性有限。经过多次查阅资料、排查编译报错与环境配置问题,最终成功完成插件的编译与部署。现将完整实操经验整理分享,希望能为有同样需求的开发者避坑。

配置环境:

  • Windows 11 64位
  • PostgreSQL 16
  • Visual Studio 2026

1. scws和zhparser源码下载

scws中文分词库(zhparser依赖)下载地址:github.com/hightman/sc… zhparser工程下载地址:github.com/kerneltrave… (已使用vs改进)

2. 将scws文件夹和zhparser文件夹放在同一层目录下(注意名称)

  • 打开文件夹 scws\win32\scws.sln文件,将工程文件自动升级到当前可用版本。
  • 打开文件夹 zhparser-master\zhparser.sln文件,将工程文件自动升级到当前可用版本。(工具集版本不匹配提示:把下拉框里的「忽略」改成 「更新为当前已安装的工具集」)。
  • 添加文件目录:在解决方案资源管理器中右键点击libscws,依次选择属性C/C++常规,在右侧附加包含目录中,添加对应路径(请根据自身实际路径调整)。
D:\project\vsProject\scws\libscws
D:\software\PostgreSQL\16\include
D:\software\PostgreSQL\16\include\server
D:\software\PostgreSQL\16\include\server\utils
D:\software\PostgreSQL\16\include\server\port
D:\software\PostgreSQL\16\include\server\port\win32
D:\software\PostgreSQL\16\include\server\port\win32_msvc
%(AdditionalIncludeDirectories)
  • 若你使用 64 位系统,可继续在该属性页面操作:点击窗口右上角的配置管理器,新建活动解决方案平台,选择新平台为x64,点击确定即可。 在这里插入图片描述
  • 为了避免生成报错,找到打开xdict.h文件,将其中的中文注释删除。 在这里插入图片描述
  • 找到config_win32.h文件,注释掉以下logf定义的代码行。 在这里插入图片描述
  • 打开 scws.h,加入以下代码块,否则编译成功后对应文件夹没有lib文件
#ifdef _WIN32
  #ifdef LIBSCWS_EXPORTS
    #define SCWS_API __declspec(dllexport)
  #else
    #define SCWS_API __declspec(dllimport)
  #endif
#else
  #define SCWS_API
#endif

scws.h完整版替换: 因为DLL 是一个动态库,如果你的代码里没有明确告诉编译器“我想把哪些函数公开给外部使用”,链接器就不会生成对应的 .lib(导入库)文件。

/**
 * @file scws.h (core include)
 * @author Hightman Mar
 * @editor set number ; syntax on ; set autoindent ; set tabstop=4 (vim)
 * $Id$
 */

#ifndef _SCWS_LIBSCWS_20070531_H_
#define _SCWS_LIBSCWS_20070531_H_

/* Windows 导出/导入宏定义 */
#ifdef _WIN32
  #ifdef LIBSCWS_EXPORTS
    #define SCWS_API __declspec(dllexport)
  #else
    #define SCWS_API __declspec(dllimport)
  #endif
#else
  #define SCWS_API
#endif

#ifdef __cplusplus
extern "C" {
#endif

#include "version.h"
#include "rule.h"
#include "xdict.h"

#define SCWS_IGN_SYMBOL     0x01
//#define   SCWS_SEG_MULTI      0x02
//#define   SCWS_XDB_USAGE      0x04
#define SCWS_DEBUG          0x08
#define SCWS_DUALITY        0x10

/* hightman.070901: multi segment policy */
#define SCWS_MULTI_NONE     0x00000     // nothing
#define SCWS_MULTI_SHORT    0x01000     // split long words to short words from left to right
#define SCWS_MULTI_DUALITY  0x02000     // split every long words(3 chars?) to two chars
#define SCWS_MULTI_ZMAIN    0x04000     // split to main single chinese char atr = j|a|n?|v?
#define SCWS_MULTI_ZALL     0x08000     // attr = ** , all split to single chars
#define SCWS_MULTI_MASK     0xff000     // mask check for multi set

#define SCWS_ZIS_USED       0x8000000

#define SCWS_YEA            (1)
#define SCWS_NA             (0)

/* data structures */
typedef struct scws_result *scws_res_t;

struct scws_result
{
    int off;
    float idf;
    unsigned char len;
    char attr[3];
    scws_res_t next;
};

typedef struct scws_topword *scws_top_t;

struct scws_topword
{
    char *word;
    float weight;
    short times;
    char attr[2];
    scws_top_t next;
};

struct scws_zchar
{
    int start;
    int end;
};

typedef struct scws_st scws_st, *scws_t;

struct scws_st
{
    xdict_t d;
    rule_t r;
    unsigned char *mblen;
    unsigned int mode;
    unsigned char *txt;
    int zis;
    int len;
    int off;
    int wend;
    scws_res_t res0;
    scws_res_t res1;
    word_t **wmap;
    struct scws_zchar *zmap;
};

/* api: init the scws handler */
SCWS_API scws_t scws_new();
SCWS_API void scws_free(scws_t s);
/* fork instance for multi-threaded usage, but they shared the dict/rules */
SCWS_API scws_t scws_fork(scws_t s);

/* mode = SCWS_XDICT_XDB | SCWS_XDICT_MEM | SCWS_XDICT_TXT */
SCWS_API int scws_add_dict(scws_t s, const char *fpath, int mode);
SCWS_API int scws_set_dict(scws_t s, const char *fpath, int mode);
SCWS_API void scws_set_charset(scws_t s, const char *cs);
SCWS_API void scws_set_rule(scws_t s, const char *fpath);

/* set ignore symbol or multi segments */
SCWS_API void scws_set_ignore(scws_t s, int yes);
SCWS_API void scws_set_multi(scws_t s, int mode);
SCWS_API void scws_set_debug(scws_t s, int yes);
SCWS_API void scws_set_duality(scws_t s, int yes);

SCWS_API void scws_send_text(scws_t s, const char *text, int len);
SCWS_API scws_res_t scws_get_result(scws_t s);
SCWS_API void scws_free_result(scws_res_t result);

SCWS_API scws_top_t scws_get_tops(scws_t s, int limit, char *xattr);
SCWS_API void scws_free_tops(scws_top_t tops);

SCWS_API scws_top_t scws_get_words(scws_t s, char *xattr);
SCWS_API int scws_has_word(scws_t s, char *xattr);

#ifdef __cplusplus
}
#endif

#endif
  • 点击生成,就可以获得libscws.lib

4. 编译zhparser

  • 添加文件目录:在解决方案资源管理器中右键点击zhparser,依次选择属性C/C++常规,在右侧附加包含目录中,添加对应路径(请根据自身实际路径调整)。
D:\project\vsProject\scws\libscws
D:\software\PostgreSQL\16\include
D:\software\PostgreSQL\16\include\server
D:\software\PostgreSQL\16\include\server\utils
D:\software\PostgreSQL\16\include\server\port
D:\software\PostgreSQL\16\include\server\port\win32
D:\software\PostgreSQL\16\include\server\port\win32_msvc
%(AdditionalIncludeDirectories)
  • 在属性属性链接器常规→** 附加库目录**添加以下路径。
D:\software\PostgreSQL\16\lib
D:\project\vsProject\zhparser-master
%(AdditionalLibraryDirectories)
  • 右键zhparser属性链接器输入附加依赖项编辑。清空现有内容,输入以下 2 个库名(直接输名字,不用带路径,链接器会通过上面的库目录找到),点击确定保存。
postgres.lib
libscws.lib
  • 将 PostgreSQL 安装目录下的postgres.lib文件,与 scws 编译完成后生成的libscws.lib文件,一同拷贝至 zhparser 项目根目录,并替换目录中原有的同名旧文件。
  • 打开 zhparser 项目中的zhparser.c文件,在文件最顶部(所有#include之后、第一个函数之前)粘贴以下代码,定义pstrdup_call函数,替换pstrdup
// 自定义pstrdup替代函数,适配PG16
char *pstrdup_call(const char *src)
{
    char *dst;
    int len;

    if (src == NULL) 
        return NULL;

    len = strlen(src) + 1;
    dst = (char *) palloc(len);
    memcpy(dst, src, len);
    return dst;
}
  • 点击生成,就可以获得zhparser.dll

5.补全文件

  • zhparser.dll 复制至 PostgreSQL 安装目录的 lib 文件夹下。
  • 将 zhparser-master 目录下的 zhparser.controlzhparser--1.0.sqlzhparser--unpackaged--1.0.sql 三个文件,拷贝到 PostgreSQL 安装目录的 share\extension 文件夹下。
  • rules.utf8.inidict.utf8.xdb 两个文件,拷贝至 PostgreSQL 安装目录的 \share\tsearch_data 文件夹下。

6.测试插件

  • 拷贝完文件后,必须重启 PostgreSQL 16 服务(仅重启 psql/pgAdmin 没用,服务未加载新拷贝的 DLL),步骤如下:
    • 按下Win+R,输入services.msc,回车打开「服务」窗口;
    • 在服务列表中找到 postgresql-x64-16(PG16 的默认服务名);
    • 右键→「重启」,等待服务重启完成(约 10 秒);
    • 重新打开 psql,连接你的数据库。
  • 服务重启后,在 psql 中再次执行。
CREATE EXTENSION zhparser;
  • 成功! 在这里插入图片描述

参考博客:blog.csdn.net/vaingloryxi…allsobaiduend~default-2-139720959-null-null.142^v102^pc_search_result_base5&utm_term=zhparser.dll&spm=1018.2226.3001.4187