上次讲到了两种库文件MyLanguageInvokeSPSSXD和InvokeMyLanguage。本节重点解析一下MyLanguageInvokeSPSSXD。
SPSS的C语言应用编程接口(SPSSXD API)在动态链接库spssxd.dll中包含两个方面的底层功能:第一种是提交操作请求给SPSS,请求的典型返回结果为错误码,通过错误码,可以得出操作结果是成功还是出现其他异常和错误。
第二种是提交信息请求给SPSS,请求的典型返回结果是所请求的信息。这些底层功能实现对SPSS的功能操作,变量字典的获取,输出结果XML工作区信息的读取,对SPSS活动数据集的操作。SPSS的C语言应用编程接口帮助文档可以在SPSS提供的可扩展性编程spssxdAPI文件夹下找到。
外部语言程序直接调用SPSS C语言应用编程接口的基本工作过程可以描述为以下步骤:
以下为SPSS提供的官方样例程序。C语言程序的主入口:
- int _tmain(int argc, _TCHAR* argv[])
- {
- //初始化传入参数个数为1
- int count = 1;
- if (argc >1)
- count = atoi(argv[1]);
-
- __time64_t stime; //time.h time类中定义的结构
- _time64( &stime );//the start time of the test
-
- //装载DLL
- int load = LoadLib();
- //判断是否成功
- if ( load != 0 ){
- std::cout << "load failure, exitcode = " << load << std::endl;
- return -1;
- }
-
- //创建暂存结果的文件
- std::string tempfile = "d:/temp/result.txt";
- std::string tempresult("-out ");
- tempresult = tempresult + tempfile;
-
- //申明状态检查
- int err = 0;
- //启动SPSS通信
- err = StartSpss(tempresult.c_str());
- if( err != 0 ){
- std::cout << "start spss failed, exitcode = " << err << std::endl;
- return -1;
- }
- //To Do Work
- for (int i=0; i<count; i++){
- //判断是否就绪
- int ready = IsBackendReady();
- if( ready != 1 ){
- std::cout << "backend is not ready, exitcode = " << ready << std::endl;
- return -1;
- }
- //确定要处理的文件
- std::vector<std::string> fList; //data file list
- filelist(fList);
- //检验并打开文件
- int index=i%(int)fList.size();
- err = getfile(fList[index].c_str());
- if (err !=0 ){
- std::cout << "get file error: filename=>" << fList[index] << " err=" << err << std::endl;
- return -1;
- }
- //测试XPath和通用功能
- XPathAndGeneralFunctions(fList[index].c_str());
- int iPosition = 0;
- Displayresult(tempfile.c_str(), iPosition);
- std::cout <<"The end of XPATH result output! \n"<<endl;
- //开始一个用户的过程
- StartProcedure("UserProc1");
- //操作数据库
- DataSourceFunctions();
- Displayresult(tempfile.c_str(), iPosition);
- //测试转轴表
- PivotTableFunctions();
- Displayresult(tempfile.c_str(), iPosition);
- //结束过程
- EndProcedure();
- //测试数据数据集
- DataStepFunctions();
- Displayresult(tempfile.c_str(), iPosition);
- }
- //终止SPSS通信
- StopSpss();
- //卸载DLL
- FreeLib();
- return 0;
- }
- 进一步深入LoadLib(),该方法由load.cpp提供,源代码如下:
- /**
- * load.c -
- * load and unload spssxd.dll dynamically.
- * COPYRIGHT
- * Copyright 2005 by SPSS Inc. All rights reserved.
- */
-
- #include "load.h"
- #include <iostream>
- using namespace std;
- //declare the function pointer.
- FP_IsBackendReady IsBackendReady = NULL;
- FP_IsXDriven IsXDriven = NULL;
- FP_StartSpss StartSpss = NULL;
- FP_StopSpss StopSpss = NULL;
- FP_Submit Submit = NULL;
- FP_QueueCommandPart QueueCommandPart = NULL;
- FP_PostSpssOutput PostSpssOutput = NULL;
- FP_GetVariableCount GetVariableCount = NULL;
- FP_GetRowCount GetRowCount = NULL;
- FP_GetVariableName GetVariableName = NULL;
- FP_GetVariableLabel GetVariableLabel = NULL;
- FP_GetVariableType GetVariableType = NULL;
- FP_GetVariableFormat GetVariableFormat = NULL;
- FP_GetVariableMeasurementLevel GetVariableMeasurementLevel = NULL;
- FP_CreateXPathDictionary CreateXPathDictionary = NULL;
- FP_RemoveXPathHandle RemoveXPathHandle = NULL;
- FP_EvaluateXPath EvaluateXPath = NULL;
- FP_GetStringListLength GetStringListLength = NULL;
- FP_GetStringFromList GetStringFromList = NULL;
- FP_RemoveStringList RemoveStringList = NULL;
- FP_GetXmlUtf16 GetXmlUtf16 = NULL;
- FP_GetHandleList GetHandleList = NULL;
- FP_GetNumericValue GetNumericValue = NULL;
- FP_GetStringValue GetStringValue = NULL;
- FP_MakeCaseCursor MakeCaseCursor = NULL;
- FP_NextCase NextCase = NULL;
- FP_RemoveCaseCursor RemoveCaseCursor = NULL;
- FP_GetVariableFormatType GetVariableFormatType = NULL;
- FP_GetCursorPosition GetCursorPosition = NULL;
-
- FP_StartPivotTable StartPivotTable = NULL;
- FP_AddDimension AddDimension = NULL;
- FP_AddStringCategory AddStringCategory = NULL;
- FP_SetFormatSpecCount SetFormatSpecCount = NULL;
- FP_SetNumberCell SetNumberCell = NULL;
- FP_AddCellFootnotes AddCellFootnotes = NULL;
- FP_AddTextBlock AddTextBlock = NULL;
- FP_StartProcedure StartProcedure = NULL;
- FP_EndProcedure EndProcedure = NULL;
-
- FP_StartDataStep StartDataStep = NULL;
- FP_CreateDataset CreateDataset = NULL;
- FP_GetCaseCountInDS GetCaseCountInDS = NULL;
- FP_InsertCase InsertCase = NULL;
- FP_DeleteCase DeleteCase = NULL;
- FP_GetVarTypeInDS GetVarTypeInDS = NULL;
- FP_GetNCellValue GetNCellValue = NULL;
- FP_GetCCellValue GetCCellValue = NULL;
- FP_SetNCellValue SetNCellValue = NULL;
- FP_SetCCellValue SetCCellValue = NULL;
- FP_EndDataStep EndDataStep = NULL;
-
- HMODULE pLib = NULL; //初始化一个句柄
- const char libName[] = "spssxd_p.dll"; //SPSS的动态链接库
- const int LOAD_FAIL = 1011;
- const int LOAD_SUCCESS = 0;
-
- //Initialize the function pointer
- void InitializeFP()
- {
- //GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址,参数为句柄加函数名,返回的是动态链接库的空间地址
- IsBackendReady = (FP_IsBackendReady)GetProcAddress(pLib,"IsBackendReady");
- //上句检查动态链接库后台已经准备就绪,设置后台准备状态为就绪布尔型
- //下句设置动态链接库驱动正确布尔型
- IsXDriven = (FP_IsXDriven)GetProcAddress(pLib,"IsXDriven");
- //设置动态链接库为SPSS开始的命令行字符串
- StartSpss = (FP_StartSpss)GetProcAddress(pLib,"StartSpss");
- //设置动态链接库为SPSS结束整型
- StopSpss = (FP_StopSpss)GetProcAddress(pLib,"StopSpss");
- //设置动态链接库为SPSS提交的命令行包括提交命令及其长度返回整型
- Submit = (FP_Submit)GetProcAddress(pLib,"Submit");
- //设置动态链接库为SPSS提交的队列命令包括提交行命令及其长度返回整型
- QueueCommandPart = (FP_QueueCommandPart)GetProcAddress(pLib,"QueueCommandPart");
- //设置动态链接库为SPSS返回结构的文本返回整型
- PostSpssOutput = (FP_PostSpssOutput)GetProcAddress(pLib,"PostSpssOutput");
- //设置动态链接库为SPSSF能取得的变量个数返回整型
- GetVariableCount = (FP_GetVariableCount)GetProcAddress(pLib,"GetVariableCount");
- //设置动态链接库为SPSSF能取得的记录行数返回整型
- GetRowCount = (FP_GetRowCount)GetProcAddress(pLib,"GetRowCount");
- //设置动态链接库为SPSS能取得的变量名称返回字符型
- GetVariableName = (FP_GetVariableName)GetProcAddress(pLib,"GetVariableName");
- //设置动态链接库为SPSS能取得的变量标签返回字符型
- GetVariableLabel = (FP_GetVariableLabel)GetProcAddress(pLib,"GetVariableLabel");
- //设置动态链接库为SPSS能取得的变量类型返回字符型
- GetVariableType = (FP_GetVariableType)GetProcAddress(pLib,"GetVariableType");
- //设置动态链接库为SPSS能取得的变量格式返回字符型
- GetVariableFormat = (FP_GetVariableFormat)GetProcAddress(pLib,"GetVariableFormat");
- //设置动态链接库为SPSS能取得的变量评价层次返回整型
- GetVariableMeasurementLevel = (FP_GetVariableMeasurementLevel)GetProcAddress(pLib,"GetVariableMeasurementLevel");
- //设置动态链接库为SPSS创建的XPATH字典返回整型
- CreateXPathDictionary = (FP_CreateXPathDictionary)GetProcAddress(pLib,"CreateXPathDictionary");
- //设置动态链接库为SPSS删除的XPATH处理返回整型
- RemoveXPathHandle = (FP_RemoveXPathHandle)GetProcAddress(pLib,"RemoveXPathHandle");
- //设置动态链接库为SPSS评估的XPATH处理(包括处理,上下文,表达式)无返回
- EvaluateXPath =(FP_EvaluateXPath)GetProcAddress(pLib,"EvaluateXPath");
- //设置动态链接库为SPSS处理的列表返回整型
- GetStringListLength = (FP_GetStringListLength)GetProcAddress(pLib,"GetStringListLength");
- //设置动态链接库为SPSS处理的字符列表返回字符
- GetStringFromList = (FP_GetStringFromList)GetProcAddress(pLib,"GetStringFromList");
- //设置动态链接库为SPSS删除处理的字符列表返回字符
- RemoveStringList = (FP_RemoveStringList)GetProcAddress(pLib,"RemoveStringList");
- //设置动态链接库为SPSS处理的XML返回字符
- GetXmlUtf16 = (FP_GetXmlUtf16)GetProcAddress(pLib,"GetXmlUtf16");
- //设置动态链接库为SPSS处理的列表无返回
- GetHandleList = (FP_GetHandleList)GetProcAddress(pLib,"GetHandleList");
- //设置动态链接库为SPSS结果和变量索引返回整型
- GetNumericValue = (FP_GetNumericValue)GetProcAddress(pLib,"GetNumericValue");
- //设置动态链接库为SPSS结果、缓冲长度和变量索引返回整型
- GetStringValue = (FP_GetStringValue)GetProcAddress(pLib,"GetStringValue");
- //创建游标 返回整型
- MakeCaseCursor = (FP_MakeCaseCursor)GetProcAddress(pLib,"MakeCaseCursor");
- //移动到下一个案例 返回整型
- NextCase = (FP_NextCase)GetProcAddress(pLib,"NextCase");
- //移除案例游标返回整型
- RemoveCaseCursor = (FP_RemoveCaseCursor)GetProcAddress(pLib,"RemoveCaseCursor");
- //由格式类型拿到变量格式类型返回整型
- GetVariableFormatType = (FP_GetVariableFormatType)GetProcAddress(pLib,"GetVariableFormatType");
- //得到游标位置
- GetCursorPosition = (FP_GetCursorPosition)GetProcAddress(pLib,"GetCursorPosition");
- //
- StartPivotTable = (FP_StartPivotTable)GetProcAddress(pLib,"StartPivotTable");
- AddDimension = (FP_AddDimension)GetProcAddress(pLib,"AddDimension");
- AddStringCategory = (FP_AddStringCategory)GetProcAddress(pLib,"AddStringCategory");
- SetFormatSpecCount = (FP_SetFormatSpecCount)GetProcAddress(pLib,"SetFormatSpecCount");
- SetNumberCell = (FP_SetNumberCell)GetProcAddress(pLib,"SetNumberCell");
- AddCellFootnotes = (FP_AddCellFootnotes)GetProcAddress(pLib,"AddCellFootnotes");
- AddTextBlock = (FP_AddTextBlock)GetProcAddress(pLib,"AddTextBlock");
- StartProcedure = (FP_StartProcedure)GetProcAddress(pLib,"StartProcedure");
- EndProcedure = (FP_EndProcedure)GetProcAddress(pLib,"EndProcedure");
-
- StartDataStep = (FP_StartDataStep)GetProcAddress(pLib,"StartDataStep");
- CreateDataset = (FP_CreateDataset)GetProcAddress(pLib,"CreateDataset");
- GetCaseCountInDS = (FP_GetCaseCountInDS)GetProcAddress(pLib,"GetCaseCountInDS");
- InsertCase = (FP_InsertCase)GetProcAddress(pLib,"InsertCase");
- DeleteCase = (FP_DeleteCase)GetProcAddress(pLib,"DeleteCase");
- GetVarTypeInDS = (FP_GetVarTypeInDS)GetProcAddress(pLib,"GetVarTypeInDS");
- GetNCellValue = (FP_GetNCellValue)GetProcAddress(pLib,"GetNCellValue");
- GetCCellValue = (FP_GetCCellValue)GetProcAddress(pLib,"GetCCellValue");
- SetNCellValue = (FP_SetNCellValue)GetProcAddress(pLib,"SetNCellValue");
- SetCCellValue = (FP_SetCCellValue)GetProcAddress(pLib,"SetCCellValue");
- EndDataStep = (FP_EndDataStep)GetProcAddress(pLib,"EndDataStep");
-
- }
-
- int LoadLib()
- {
- //判断是否得到句柄pLib
- if(NULL == pLib){ //libName = "spssxd.dll"
- //find out spssxd.dll module, it will success when spss drive
- pLib = GetModuleHandle(libName);//如果SPSS是运行的,这里获得名为spssxd.dll的句柄
- //find out spssxd.dll module failure, load it.
- if(NULL == pLib) {//SPSS程序此时没有运行,所以这里句柄为Null
- pLib = LoadLibrary(libName);//重新载入名为spssxd.dll的链接库道地址空间,进而访问该资源
- }
- //load spssxd.dll module success, initialize the function pointer这里成功载入动态链接库
- if (pLib) {//载入动态链接库spssxd.dll,并开始初始化功能指针
- InitializeFP();
- }
- //load failure
- else {
- return LOAD_FAIL;//装载失败
- }
- }
- return LOAD_SUCCESS;//装载成功
- }
-
- void FreeLib()
- {
- FreeLibrary(pLib);
- pLib= NULL;
-
- IsBackendReady = NULL;
- IsXDriven = NULL;
- StartSpss = NULL;
- StopSpss = NULL;
- Submit = NULL;
- QueueCommandPart = NULL;
- PostSpssOutput = NULL;
- GetVariableCount = NULL;
- GetRowCount = NULL;
- GetVariableName = NULL;
- GetVariableLabel = NULL;
- GetVariableType = NULL;
- GetVariableFormat = NULL;
- GetVariableMeasurementLevel = NULL;
- CreateXPathDictionary = NULL;
- RemoveXPathHandle = NULL;
- EvaluateXPath = NULL;
- GetStringListLength = NULL;
- GetStringFromList = NULL;
- RemoveStringList = NULL;
- GetXmlUtf16 = NULL;
- GetHandleList = NULL;
- GetNumericValue = NULL;
- GetStringValue = NULL;
- MakeCaseCursor = NULL;
- NextCase = NULL;
- RemoveCaseCursor = NULL;
- GetVariableFormatType = NULL;
- GetCursorPosition = NULL;
- StartPivotTable = NULL;
- AddDimension = NULL;
- AddStringCategory = NULL;
- SetFormatSpecCount = NULL;
- SetNumberCell = NULL;
- AddCellFootnotes = NULL;
- AddTextBlock = NULL;
- StartProcedure = NULL;
- EndProcedure = NULL;
- StartDataStep = NULL;
- CreateDataset = NULL;
- GetCaseCountInDS = NULL;
- InsertCase = NULL;
- DeleteCase = NULL;
- GetVarTypeInDS = NULL;
- GetNCellValue = NULL;
- GetCCellValue = NULL;
- SetNCellValue = NULL;
- SetCCellValue = NULL;
- EndDataStep = NULL;
- }