您的位置:首页 > 编程语言 > Lua

C++与LUA间的交互

2014-03-02 10:28 435 查看
此篇文章只面向于对迅雷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);

}

LUA端

——————————————————————————————————

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))


输出

++++————————————————————————————————————



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: