lua加载dll文件套路

在做游戏的时候,经常会要使用dll来封装库给lua来使用。本文将用于说明如何来通过lua来加载dll。

lua加载代码

在loadlib.c文件中的127lines


static void *ll_load (lua_State *L, const char *path) {
  HINSTANCE lib = LoadLibraryA(path);
  if (lib == NULL) pusherror(L);
  return lib;
}


static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
  lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);
  if (f == NULL) pusherror(L);
  return f;
}

当加载dll文件的时候,分为两步来走:

加载dll文件

首先通过预定的package.cpath搜索目录来查找dll文件是否存在。
这里是一个指定加载目录的实例

package.cpath = package.cpath .. ';c:/my_lua_dll_lib/?dll;'

找到lua的入口函数

通过GetProcAddress到你的dll文件中查找入口函数。这个函数名是一个固定的:
loadlib.c文件中能读到这个代码:

/* prefix for open functions in C libraries */
#define LUA_POF     "luaopen_"

#define POF     LUA_POF

static int loader_C (lua_State *L) {
  const char *funcname;
  const char *name = luaL_checkstring(L, 1);
  const char *filename = findfile(L, name, "cpath");
  if (filename == NULL) return 1;  /* library not found in this path */
  funcname = mkfuncname(L, name);
  if (ll_loadfunc(L, filename, funcname) != 0)
    loaderror(L, filename);
  return 1;  /* library loaded successfully */
}

static const char *mkfuncname (lua_State *L, const char *modname) {
  const char *funcname;
  const char *mark = strchr(modname, *LUA_IGMARK);
  if (mark) modname = mark + 1;
  funcname = luaL_gsub(L, modname, ".", LUA_OFSEP);
  funcname = lua_pushfstring(L, POF"%s", funcname);
  lua_remove(L, -2);  /* remove 'gsub' result */
  return funcname;
}

输入的参数只有”your_dll_name”,在mkfuncname函数将会拼接函数。

dll编写

导出的细节

lua是一个默认为c语言的引擎,在使用vs来编写dll的时候,默认创建源文件的时候将会为cpp文件。所以这个里面写的function的时候,默认是使用的c++的语法。当被导出的时候我们可以通过depends工具来分析dll中的function:
这里写图片描述

如果代码是C和C++混编的时候,注意这个点。如果函数是在cpp中编写的那就需要在函数开始的地方加上:

extern "C"

实例

参考

//#include "stdio.h"
#include "windows.h"
#ifdef _cplusplus  
extern "C"{
#endif
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

extern  int  isquare(lua_State *L);
extern  int  alert(lua_State *L);
#ifdef _cplusplus
}
#endif

int luaopen_add(lua_State *L){
    lua_register(
            L,               /* Lua 状态机 */
            "square",        /*Lua中的函数名 */
            isquare          /*当前文件中的函数名 */
            );  
   lua_register(L,"alert",alert);
//    lua_register(L,"cube",icube);
    return 0;
}


int alert(lua_State *L)
{
    const char * desc = lua_tostring(L,-1);
    MessageBox(NULL,desc,"alert",MB_OK);
    return 1;
}

int isquare(lua_State *L){              /* C中的函数名 */
    float rtrn = lua_tonumber(L, -1);      /* 从Lua虚拟机里取出一个变量,这个变量是number类型的 */
    //printf("Top of square(), nbr=%f\n",rtrn);
    lua_pushnumber(L,rtrn*rtrn);           /* 将返回值压回Lua虚拟机的栈中 */
    return 1;                              /* 这个返回值告诉lua虚拟机,我们往栈里放入了多少个返回值 */
}

C加载函数实验

// test_load_dll.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <string>
#include <iostream>
#include <sstream>

#include <lua.hpp>

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

typedef int(*lua_CFunction) (lua_State *L);

int main(int argn, char *argv[])
{
    if (argn != 2)
    {
        return -100;
    }

    std::string dll = argv[1];
    std::stringstream ss;
    ss << "xxxxxxxxxxxxxxxxxxxxx" << dll << ".dll";
    std::string dll_name = ss.str();
    HINSTANCE lib = ::LoadLibraryA(dll_name.c_str());
    if (lib == NULL) {
        std::cerr << "LoadLibraryA failed, errorcode: " << ::GetLastError() << std::endl;
        return -1;
    }

    ss.str("");
    ss << "luaopen_" << dll;
    std::string sym = ss.str();
    lua_CFunction f = (lua_CFunction)::GetProcAddress((HINSTANCE)lib, sym.c_str());
    if (f == NULL)
    {
        std::cerr << "GetProcAddress failed: " << ::GetLastError() << std::endl;
    }
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值