上次讲到了两种库文件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;
}