# OCCIWapper **Repository Path**: mini-tiger/occiwapper ## Basic Information - **Project Name**: OCCIWapper - **Description**: oracle OCCI wapper to c - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-07 - **Last Updated**: 2026-03-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OCCIWapper OCCIWapper 是一个 Oracle C++ Call Interface (OCCI) 的 C 语言包装器 DLL 项目。它将 C++ 接口的 OCCI 库封装为 C 接口,使不支持 C++ 的编程语言(如 C、Delphi、Python ctypes 等)也能方便地访问 Oracle 数据库。 ## 项目概述 Oracle OCCI 是一个功能强大的 C++ 数据库访问接口,但由于其 C++ 特性(如异常处理、STL、类继承等),难以在非 C++ 环境中直接使用。OCCIWapper 通过以下方式解决了这个问题: - 将 OCCI 的 C++ 类封装为 C 结构体 - 使用虚函数表(vtable)实现多态和方法调用 - 提供 C 和 C++ 两种调用方式 - 支持多字符集编码转换 - 线程安全的错误处理机制 ## 功能特性 ### 核心功能 - ? 环境管理(Environment)- 创建和管理 OCCI 环境 - ? 数据库连接(Connection)- 连接 Oracle 数据库,支持事务控制 - ? SQL 语句执行(Statement)- 执行查询和更新操作 - ? 结果集处理(ResultSet)- 遍历和获取查询结果 - ? 参数绑定 - 支持多种数据类型的参数设置 ### 支持的数据类型 | 类型 | 说明 | |------|------| | `int` / `unsigned int` | 32位整数 | | `long long` / `unsigned long long` | 64位整数 | | `float` / `double` | 浮点数 | | `char*` / `std::string` | 字符串 | | `CLOB` | 大文本对象 | | `Number` | Oracle 数字类型 | ### 字符集支持 支持多种字符集编码转换: - UTF-8 (65001) - GBK/GB2312 (936) - Big5 (950) - Shift-JIS (932) - Latin1/2/9 - Windows 代码页 (1250-1256, 874 等) - 以及其他常用编码 ## 项目结构 ``` OCCIWapper/ ├── OCCIWapper/ # 主 DLL 项目目录 │ ├── OCCIWapper.h # 头文件(C/C++ 接口定义) │ ├── OCCIWapper.cpp # 实现文件 │ ├── dllmain.cpp # DLL 入口点 │ ├── stdafx.h # 预编译头 │ ├── targetver.h # 目标 Windows 版本 │ └── Makefile # 模块编译配置 ├── test/ # 测试程序目录 │ ├── main.cpp # 测试代码 │ ├── stdafx.h # 预编译头 │ ├── targetver.h # 目标 Windows 版本 │ └── Makefile # 模块编译配置 ├── lib/ │ └── occi/ # Oracle OCCI 库文件 │ ├── include/ # OCCI 头文件 │ ├── oraocci11.lib # OCCI 导入库 │ ├── oraocci11.dll # OCCI 运行时库 │ ├── oraociei11.dll # OCCI 国际化库 │ └── oci.dll # OCI 运行时库 ├── .config/ # 编译器配置 │ ├── builder.mk # 主构建脚本 │ ├── compiler_VS2017.mk # VS2017 配置 │ └── compiler_vs2008.mk # VS2008 配置 ├── .vscode/ # VS Code 配置 │ ├── c_cpp_properties.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── build/ # 编译输出目录 │ └── x64/ │ ├── Debug/ # 调试版本输出 │ └── Release/ # 发布版本输出 ├── Makefile # 主 Makefile └── README.md # 本文件 ``` ## 编译要求 ### 开发环境 - **操作系统**: Windows (支持 Windows XP 及以上版本) - **编译器**: Microsoft Visual Studio 2008 或更高版本 - **构建工具**: GNU Make (通过 MinGW/MSYS 或 Cygwin) ### Oracle 客户端要求 - Oracle Instant Client 11g 或更高版本 - 需要 OCCI 库文件(oraocci11.dll 等) ## 编译说明 ### 使用 Make 编译 ```bash # 编译所有目标(Release 版本) make # 编译 Debug 版本 make debug # 编译 Release 版本 make release # 清理编译输出 make clean ``` ### 编译配置选项 在根目录的 `Makefile` 中可以配置以下选项: | 变量 | 说明 | 默认值 | |------|------|--------| | `VS_VERSION` | Visual Studio 版本 | 2008 | | `ARCH` | 目标架构 (x86/x64) | 自动检测 | | `BUILD_TYPE` | 构建类型 (Debug/Release) | Debug | | `RUNTIME` | C++ 运行时库 (static/dynamic) | static | | `CHARSET` | 字符集 (UNICODE/MBCS) | UNICODE | ## 使用示例 ### C++ 方式使用(推荐) ```cpp #include "OCCIWapper.h" #include int main() { // 设置 Oracle 字符集环境变量 SetEnvironmentVariableA("NLS_LANG", "SIMPLIFIED CHINESE_CHINA.ZHS16GBK"); try { // 使用 RAII 守护类自动管理资源 OCCI_Guardian env = OCCI_Environment::CreateEnvironment("ZHS16GBK", "ZHS16GBK"); OCCI_Guardian conn = env->createConnection("用户名", "密码", "主机:端口/服务名"); OCCI_Guardian stmt = conn->createStatement("SELECT * FROM test_table WHERE id = :1"); // 绑定参数 stmt->setInt(1, 100); // 执行查询 OCCI_Guardian rs = stmt->executeQuery(); // 遍历结果集 while (rs->next()) { std::cout << "ID: " << rs->getInt(1) << std::endl; std::cout << "Name: " << rs->getString(2) << std::endl; } // 提交事务 conn->commit(); } catch (OCCIWapperException& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; } ``` ### C 方式使用 ```c #include "OCCIWapper.h" #include int main() { // 创建环境 OCCI_Environment* env = OCCI_Environment_CreateEnvironment("UTF8", "UTF8", OCCI_DEFAULT); if (!env) { ThreadLocalBuffer* err = GetThreadLocalBuffer(); printf("Error: %s\n", err->charBuffer); return 1; } // 创建连接 OCCI_Connection* conn = env->vtable->CreateConnection(env, "用户名", "密码", "主机:端口/服务名"); if (!conn) { // 错误处理... env->vtable->Close(env); return 1; } // 创建语句 OCCI_Statement* stmt = conn->vtable->CreateStatement(conn, "SELECT * FROM users"); if (!stmt) { conn->vtable->Close(conn); env->vtable->Close(env); return 1; } // 执行查询 OCCI_ResultSet* rs = stmt->vtable->ExecuteQuery(stmt, NULL); if (rs) { // 遍历结果 while (rs->vtable->Next(rs) == DATA_AVAILABLE) { occi_int64_t id = rs->vtable->GetInt(rs, 1); occi_int128_t name = rs->vtable->GetString(rs, 2); printf("ID: %d, Name: %s\n", id.lo, name.str); } rs->vtable->Close(rs); } // 清理资源 stmt->vtable->Close(stmt); conn->vtable->Close(conn); env->vtable->Close(env); return 0; } ``` ## API 参考 ### 环境管理 (OCCI_Environment) ```c // 创建环境 OCCI_Environment* OCCI_Environment_CreateEnvironment( const char* charset, // 数据库字符集 const char* ncharset, // 国家字符集 Mode mode // 环境模式 ); // 关闭环境 void OCCI_Environment_Close(OCCI_Environment* env); ``` ### 连接管理 (OCCI_Connection) ```c // 创建连接 OCCI_Connection* OCCI_Connection_Create( OCCI_Environment* env, const char* user, // 用户名 const char* password, // 密码 const char* db // 连接字符串 ); // 事务控制 void OCCI_Connection_Commit(OCCI_Connection* conn); void OCCI_Connection_Rollback(OCCI_Connection* conn); // 关闭连接 void OCCI_Connection_Close(OCCI_Connection* conn); ``` ### 语句执行 (OCCI_Statement) ```c // 创建语句 OCCI_Statement* OCCI_Statement_Create( OCCI_Connection* conn, const char* sql // SQL 语句(可选) ); // 设置 SQL void OCCI_Statement_SetSQL(OCCI_Statement* stmt, const char* sql); // 参数绑定 void OCCI_Statement_SetInt(OCCI_Statement* stmt, unsigned int index, int value); void OCCI_Statement_SetString(OCCI_Statement* stmt, unsigned int index, const char* value); // ... 其他类型类似 // 执行操作 unsigned int OCCI_Statement_ExecuteUpdate(OCCI_Statement* stmt); // INSERT/UPDATE/DELETE OCCI_ResultSet* OCCI_Statement_ExecuteQuery(OCCI_Statement* stmt); // SELECT // 关闭语句 void OCCI_Statement_Close(OCCI_Statement* stmt); ``` ### 结果集 (OCCI_ResultSet) ```c // 移动到下一条记录 Status OCCI_ResultSet_Next(OCCI_ResultSet* rs); // 获取数据 int OCCI_ResultSet_GetInt(OCCI_ResultSet* rs, unsigned int colIndex); long long OCCI_ResultSet_GetInt64(OCCI_ResultSet* rs, unsigned int colIndex); double OCCI_ResultSet_GetDouble(OCCI_ResultSet* rs, unsigned int colIndex); const char* OCCI_ResultSet_GetString(OCCI_ResultSet* rs, unsigned int colIndex); // 关闭结果集 void OCCI_ResultSet_Close(OCCI_ResultSet* rs); ``` ## 错误处理 OCCIWapper 提供两种错误处理方式: ### 1. C++ 异常方式(推荐) 使用 `OCCI_Guardian` 守护类和 `OCCIWapperException` 异常: ```cpp try { OCCI_Guardian env = OCCI_Environment::CreateEnvironment(...); // ... 其他操作 } catch (OCCIWapperException& e) { // e.what() 返回错误信息 // e.getErrorCode() 返回错误代码 } ``` ### 2. C 方式错误检查 通过返回值和线程本地缓冲区获取错误信息: ```c OCCI_Environment* env = OCCI_Environment_CreateEnvironment(...); if (!env) { ThreadLocalBuffer* err = GetThreadLocalBuffer(); printf("Error %d: %s\n", err->errorCode, err->charBuffer); } ``` ## 字符集转换 OCCIWapper 提供字符集转换函数: ```c // 转换字符串编码 int OCCI_ConvertCharset( CharsetCP srcCP, // 源编码 CharsetCP destCP, // 目标编码 const char* src, // 源字符串 int srcSize, // 源缓冲区大小 char* dest, // 目标缓冲区 int destSize // 目标缓冲区大小 ); // 使用线程本地缓冲区转换(返回的指针无需释放) char* OCCI_ConvertCharsetTLS(CharsetCP srcCP, CharsetCP destCP, const char* src); ``` ## 注意事项 1. **字符集设置**: 在连接数据库前,确保设置正确的 `NLS_LANG` 环境变量 2. **资源管理**: 使用 `OCCI_Guardian` 类可以自动管理资源生命周期 3. **线程安全**: 错误信息存储在线程本地缓冲区中,是线程安全的 4. **DLL 依赖**: 运行时需要 Oracle OCCI DLL 文件在同一目录或系统 PATH 中 ## 许可证 本项目采用 MIT 许可证,详见 LICENSE 文件。 ## 贡献 欢迎提交 Issue 和 Pull Request。 ## 联系方式 如有问题或建议,请通过 GitHub Issues 联系。 --- **注意**: 本项目需要 Oracle 客户端库,请确保您拥有合法的 Oracle 使用许可。