此篇文章只面向于对迅雷BOLT引擎比较熟悉,但又不知道如何实现C++与LUA间的交互的朋友,如果你对迅雷提供的这个界面开发引擎感兴趣的话,请先学习一番再回来观看。
在官方给出的例子程序工程中,我们可以利用其固有的框架进行开发,省去多余的重复劳动。
在工程的解决方案视图中找到core项目,关于C++与LUA间的交互都有core.dll动态库进行处理,我们只需要在特定的位置和文件中进行声明和调用,编写开发即可。
我们可以在C++中声明一个简单的加减法函数,让后实现在LUA中的调用。
完整代码如下:如果觉得太多太复杂的话,我们只需要关注标红的代码即可。
MyCLass.h中关于此函数的声明
______________________________
#include <vector>
#include <string>
#include <ShellApi.h>
using std::string;
typedef void (*funcResultCallBack) (DWORD dwUserData1,DWORD dwUserData2,int nResult);
struct CallbackNode
{
funcResultCallBack pfnCallBack;
DWORD dwUserData1;
DWORD dwUserData2;
};
class MyClass
{
public:
MyClass(void);
~MyClass(void);
public:
int FindZuoBiao();
void DeletIcon();
void InitNid(HWND hwind);
string FindExePath();
int jianfa(int lhs,int rhs);
int Add(int lhs,int rhs);
string Data(string lhs);
int AttachResultListener(DWORD dwUserData1,DWORD dwUserData2,funcResultCallBack pfnCallBack);
protected:
void FireResultEvent(int nResult);
std::vector<CallbackNode> m_allCallBack;
};
MyCLass.cpp中关于此函数的实现
______________________________
#include "StdAfx.h"
#include ".\myclass.h"
#include <tchar.h>
#include "ShellAPI.h"
#include "resource.h"
#include "Commctrl.h"
#include <iostream>
#include<BaseTsd.h>
#include<cstdint>
#include <atlstr.h>
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
#define WM_IAWENTRAY WM_USER+105
using namespace std;
NOTIFYICONDATA nid;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
// Dialog Data
//{{AFX_DATA(CConnDlg)
//enum { IDD = IDD_CONN_DIALOG };
//CListCtrlm_List;
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
MyClass::MyClass(void)
{
}
MyClass::~MyClass(void)
{
}
int MyClass::Add(int lhs,int rhs)
{
int result = lhs + rhs;
FireResultEvent(result);
return result;
}
int MyClass::jianfa(int lhs,int rhs)
{
int result = lhs - rhs;
FireResultEvent(result);
return result;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_IAWENTRAY:
if(wParam == IDI_ICON1){
if(lParam == WM_LBUTTONDOWN){
//还可以在这个地方加入一个菜单,鼠标右键单击时显示
ShowWindow(hwnd, SW_SHOWNORMAL);
return TRUE;
}
}
return FALSE;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
void MyClass::DeletIcon()
{
Shell_NotifyIcon(
NIM_DELETE,
&nid
);
}
void MyClass::InitNid(HWND hwind)
{
MSG msg ;
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);//该结构体大小
nid.hWnd=hwind; //窗口句柄
nid.uID=(UINT)IDI_ICON1; //图标句柄
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ; //图标有效|自定义消息有效|鼠标指向显示文字有效
nid.uCallbackMessage=WM_IAWENTRAY;//自定义的消息名称
nid.hIcon=LoadIcon(GetModuleHandle(0),MAKEINTRESOURCE(IDI_ICON1));
// LoadIcon(NULL,MAKEINTRESOURCE(IDI_ICON1)); //图标句柄
strcpy(nid.szTip,"迅雷加速器");//鼠标指向所显示的文字
Shell_NotifyIcon(
NIM_ADD,
&nid
);
//ShowWindow (hwind, SW_HIDE) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
RECT rccc;
GetWindowRect((HWND)GetModuleHandle(0),&rccc) ;
}/*
void OnMYMESSAGE(WPARAM wParam,LPARAM lParam)
{
int nRetCode = 0;
UINT uID;//发出该消息的图标的ID
UINT uMouseMsg;//鼠标动作
POINT pt;
uID = (UINT)wParam;
uMouseMsg=(UINT) lParam;
if(uMouseMsg==WM_RBUTTONDOWN)//如果是单击右键
{
switch(uID)
{
case IDI_ICON1://如果是我们的图标
GetCursorPos(&pt);//取得鼠标位置
//AfxGetApp()-> m_pMainWnd->ShowWindow(SW_SHOWNORMAL);//显示程序窗口
break;
default:
}
}
}
return nRetCode;
}*/
string MyClass::FindExePath()
{
TCHAR szFilePath[MAX_PATH + 1];
GetModuleFileName(NULL, szFilePath, MAX_PATH);
// FireResultEvent(szFilePath);
return szFilePath;
}
string MyClass::Data(string lhs)
{
HRESULT hr;
try
{
hr = m_pConnection.CreateInstance("ADODB.Connection");
CString strLink;//连接字符串
strLink.Format("Provider=SQLOLEDB;server=(local);UID=sa;PWD=yancai1991;database=BookManage");
m_pConnection->Open((_bstr_t)strLink,"","",NULL);
}
catch(_com_error e)///捕捉异常
{
CString errormessage;
errormessage.Format("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage());
//AfxMessageBox(errormessage);///显示错误信息
}
CString sql="select * from ";
sql += lhs.c_str();
m_pRecordset.CreateInstance(__uuidof(Recordset));
m_pRecordset->Open(_bstr_t(sql),m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
while(!m_pRecordset->adoEOF)
{
lhs += (_bstr_t)m_pRecordset->GetCollect("bookname");
m_pRecordset->MoveNext();
}
m_pRecordset->Close();
return lhs;
}
int MyClass::AttachResultListener(DWORD dwUserData1,DWORD dwUserData2,funcResultCallBack pfnCallBack)
{
CallbackNode newNode;
newNode.pfnCallBack = pfnCallBack;
newNode.dwUserData1 = dwUserData1;
newNode.dwUserData2 = dwUserData2;
m_allCallBack.push_back(newNode);
return 0;
}
void MyClass::FireResultEvent(int nResult)
{
for(size_t i = 0;i < m_allCallBack.size();++ i)
{
m_allCallBack[i].pfnCallBack(m_allCallBack[i].dwUserData1,m_allCallBack[i].dwUserData2,nResult);
}
}
LuaMyCLass.h中关于此函数的声明
______________________________
#pragma once
#include "./MyClass.h"
#define MY_CLASS_LUA_CLASS "HelloBolt.MyClass"
#define MY_CLASS_FACTORY_LUA_CLASS "HelloBolt.MyClass.Factory.Class"
#define MY_CLASS_FACTORY_LUA_OBJ "HelloBolt.MyClass.Factory"
class LuaMyClass
{
public:
static int FindZuoBiao(lua_State* luaState);
static int DeletIcon(lua_State* luaState);
static int InitNid(lua_State* luaState);
static int FindExePath(lua_State* luaState);
static int jianfa(lua_State* luaState);
static int Data(lua_State* luaState);
static int Add(lua_State* luaState);
static int AttachResultListener(lua_State* luaState);
static int DeleteSelf(lua_State* luaState);
static void LuaListener(DWORD dwUserData1,DWORD dwUserData2,int nResult);
public:
static void RegisterClass(XL_LRT_ENV_HANDLE hEnv);
};
//为了能创建MyClass Instance,必须定义一个类厂单件
class LuaMyClassFactory
{
public:
MyClass* CreateInstance();
public:
static LuaMyClassFactory* __stdcall Instance(void*);
static int CreateInstance(lua_State* luaState);
public:
static void RegisterObj(XL_LRT_ENV_HANDLE hEnv);
};
LuaMyCLass.cpp中关于此函数的实现
______________________________
#include "StdAfx.h"
#include ".\luamyclass.h"
#include <atlstr.h>
int LuaMyClass::Add(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
int lhs = static_cast<int>(lua_tointeger(luaState,2));//获取LUA端的函数参数
int rhs = static_cast<int>(lua_tointeger(luaState,3));
int result = (*ppMyClass)->Add(lhs,rhs);//调用C++端声明的ADD函数
lua_pushinteger(luaState,result);//返回结果到LUA端
return 1;
}
lua_pushnil(luaState);
return 1;
}
int LuaMyClass::jianfa(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
int lhs = static_cast<int>(lua_tointeger(luaState,2));
int rhs = static_cast<int>(lua_tointeger(luaState,3));
int result = (*ppMyClass)->jianfa(lhs,rhs);
lua_pushinteger(luaState,result);
return 1;
}
lua_pushnil(luaState);
return 1;
}
int LuaMyClass::DeletIcon(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
//int lhs = static_cast<int>(lua_tointeger(luaState,2));
//int rhs = static_cast<int>(lua_tointeger(luaState,3));
(*ppMyClass)->DeletIcon();
return 1;
}
lua_pushnil(luaState);
return 1;
}
int LuaMyClass::Data(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
string lhs = static_cast<string>(lua_tostring(luaState,2));
// CString rhs = static_cast<CString>(lua_tostring(luaState,3));
string result = (*ppMyClass)->Data(lhs);
CString ss = result.c_str();
//result += "After";
char s[100];
strncpy(s,(LPCTSTR)ss,sizeof(s));
lua_pushstring(luaState,s);
return 1;
}
lua_pushnil(luaState);
return 1;
}
int LuaMyClass::FindExePath(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
//int lhs = static_cast<int>(lua_tointeger(luaState,2));
//int rhs = static_cast<int>(lua_tointeger(luaState,3));
string result = (*ppMyClass)->FindExePath();
CString ss = result.c_str();
char s[100];
strncpy(s,(LPCTSTR)ss,sizeof(s));
//const char *s = result;
lua_pushstring(luaState,s);
return 1;
}
lua_pushnil(luaState);
return 1;
}
int LuaMyClass::InitNid(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
HWND hwind = (HWND)(lua_touserdata(luaState,2));
(*ppMyClass)->InitNid(hwind);
//CString ss = result.c_str();
//char s[100];
//strncpy(s,(LPCTSTR)ss,sizeof(s));
//const char *s = result;
//lua_pushinteger(luaState,result);
return 1;
}
lua_pushnil(luaState);
return 1;
}
/*int LuaMyClass::FindZuoBiao(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
HWND hwind = (HWND)(lua_touserdata(luaState,2));
int result = (*ppMyClass)->FindZuoBiao();
lua_pushinteger(luaState,result);
return 1;
}
lua_pushnil(luaState);
return 1;
}*/
int LuaMyClass::AttachResultListener(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass && (*ppMyClass))
{
if(!lua_isfunction(luaState,2))
{
return 0;
}
//如果事件可以Detach,如何正确的释放这个lua function
long functionRef = luaL_ref(luaState,LUA_REGISTRYINDEX);
(*ppMyClass)->AttachResultListener(reinterpret_cast<DWORD>(luaState),functionRef,LuaMyClass::LuaListener);
}
return 0;
}
int LuaMyClass::DeleteSelf(lua_State* luaState)
{
MyClass** ppMyClass= reinterpret_cast<MyClass**>(luaL_checkudata(luaState,1,MY_CLASS_LUA_CLASS));
if(ppMyClass)
{
delete (*ppMyClass);
}
return 0;
}
void LuaMyClass::LuaListener(DWORD dwUserData1,DWORD dwUserData2,int nResult)
{
lua_State* luaState = reinterpret_cast<lua_State*>(dwUserData1);
int nNowTop = lua_gettop(luaState);
lua_rawgeti(luaState,LUA_REGISTRYINDEX,dwUserData2 );
lua_pushinteger(luaState,nResult);
//Bolt中要求使用XLLRT_LuaCall代替调用lua_pcall
//以获得更高稳定性和更多虚拟机状态信息
int nLuaResult = XLLRT_LuaCall(luaState,1,0,L"LuaMyClass::LuaListener");
//调用完成之后回退luaState到调用之前的状态
//如果被调用的lua代码段有返回值,
//请在此前处理并且注意XLLRT_LuaCall的返回值(nLuaResult变量)确认脚本正确执行
lua_settop(luaState,nNowTop);
return ;
}
//函数注册绑定
static XLLRTGlobalAPI LuaMyClassMemberFunctions[] =
{
//{"FindZuoBiao",LuaMyClass::FindZuoBiao},
{"DeletIcon",LuaMyClass::DeletIcon},
{"InitNid",LuaMyClass::InitNid},
{"FindExePath",LuaMyClass::FindExePath},
{"jianfa",LuaMyClass::jianfa},
{"Add",LuaMyClass::Add},
{"Data",LuaMyClass::Data},
{"AttachResultListener",LuaMyClass::AttachResultListener},
{"__gc",LuaMyClass::DeleteSelf},
{NULL,NULL}
};
/*
static XLLRTGlobalAPI LuaMyClassMemberFunctions[] =
{
{"jianfa",LuaMyClass::jianfa},
{"AttachResultListener",LuaMyClass::AttachResultListener},
{"__gc",LuaMyClass::DeleteSelf},
{NULL,NULL}
};*/
void LuaMyClass::RegisterClass(XL_LRT_ENV_HANDLE hEnv)
{
if(hEnv == NULL)
{
return;
}
long nLuaResult = XLLRT_RegisterClass(hEnv,MY_CLASS_LUA_CLASS,LuaMyClassMemberFunctions,NULL,0);
}
//------------------------------------------------------------------
MyClass* LuaMyClassFactory::CreateInstance()
{
return new MyClass();
}
int LuaMyClassFactory::CreateInstance(lua_State* luaState)
{
MyClass* pResult = new MyClass();
XLLRT_PushXLObject(luaState,MY_CLASS_LUA_CLASS,pResult);
return 1;
}
LuaMyClassFactory* __stdcall LuaMyClassFactory::Instance(void*)
{
static LuaMyClassFactory* s_pTheOne = NULL;
if(s_pTheOne == NULL)
{
s_pTheOne = new LuaMyClassFactory();
}
return s_pTheOne;
}
static XLLRTGlobalAPI LuaMyClassFactoryMemberFunctions[] =
{
{"CreateInstance",LuaMyClassFactory::CreateInstance},
{NULL,NULL}
};
void LuaMyClassFactory::RegisterObj(XL_LRT_ENV_HANDLE hEnv)
{
if(hEnv == NULL)
{
return ;
}
XLLRTObject theObject;
theObject.ClassName = MY_CLASS_FACTORY_LUA_CLASS;
theObject.MemberFunctions = LuaMyClassFactoryMemberFunctions;
theObject.ObjName = MY_CLASS_FACTORY_LUA_OBJ;
theObject.userData = NULL;
theObject.pfnGetObject = (fnGetObject)LuaMyClassFactory::Instance;
XLLRT_RegisterGlobalObj(hEnv,theObject);
}
——————————————————————————————————
local myClassFactory = XLGetObject("HelloBolt.MyClass.Factory") local myClass = myClassFactory:CreateInstance() --myClass:AttachResultListener(function(result) XLMessageBox("result is "..result) end) XLMessageBox(myClass:ADD(100,200)) XLMessageBox(myClass:Jjianfa(100,200))
输出
++++————————————————————————————————————