C++与LUA间的交互

此篇文章只面向于对迅雷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))


输出
++++————————————————————————————————————


 

猜你喜欢

转载自blog.csdn.net/jianyuling199/article/details/20282229
今日推荐