25 Jun 2016
前言
本文记录了一次安装Macvim遇到的问题和解决办法,并提到了如何从终端启动Macvim。
brew install macvim 成功,但启动报错
今天重装了Mac系统(10.11.5 El Capitan,你问Mac居然也重装系统?我只是想要一块干净的硬盘。). 折腾完系统,在装回Macvim的时候遇到了问题。
我是使用Hombrew来安装的,在安装过程中brew下载了一些依赖的包。最后安装完成,在执行完
brew linkapps macvim
生成一个链接到Applications目录之后,我立马敲了
mvim
来启动Macvim, 让我吃惊的是,居然报错了!
Fatal Python error : PyThreadState_Get : no current thread
这是我在iterm2窗口中看到的错误信息,虽然Macvim跑起来了,但是很明显python报错了,这意味着vim中使用Python的插件可能都会不能工作, 确实如此YouCompleteMe首当其冲,事实证明,后来我在逐个注释掉
.vimrc
中用到了Python的插件以排查问题的时候,把YCM注释掉了Python就不报错了。
于是google了一下报错信息,果然在YCM的issue里有关于这个问题的讨论,YCM作者一直在甩锅:
Just tried using the latest MacVim on my OS X Mountain Lion and everything works. So this is somehow caused by your machine configuration in some way, sorry.
大意就是:”别特么来烦我,这明显是你Mac系统配置问题,去换一个官方最新的Macvim版本吧。”
看了好几个关于这个问题的issue最后看到了YCM作者最关键的一个回答:
The version of Python that YCM is linked to when being built and the version of Python linked into your Vim binary have to match, yes. If they don’t, a problem like the one you’re experiencing might ensue.
意思是:”构建YCM使用的Python版本必须和构建Vim使用的Python版本必须匹配,否则就可能出来这个问题。”
...
阅读全文 ...
31 May 2016
ps: 2016年6月的WWDC上,Mac操作系统正式更名为macOS, 与iOS, watchOS, tvOS的命名风格终于统一了。
前言
本文记录了在macOS上使用c++为lua编写动态库的过程,分享一个容易翻车的坑。
Lua Version: 5.1
问题描述
在PIL第26章:《从Lua调用C》,介绍了从lua调用C程序的方法,即扩展lua, 用c++来为lua编写扩展库。
文中提到了扩展lua的两种方式:
把c++代码编译为为动态库,使用lua的动态链接功能来加载c++的模块(即,require “cpplib”的方式, 这里cpplib为一个例子,比如我编译为libcpplib.so, 就需要像这样来加载这个动态库。)
把编写好的c++模块加入到lua源码,重新编译lua可执行程序,这样c++模块就成为了lua的一部分(类似lua标准库string,math等等)
第二种方式–重新编译lua很简单,按照书中所说,把写好的c++模块注册函数
luaopen_mylib
添加到
luaL_openlibs
会打开的标准库列表里。(在linit.c中)
经过我在mac上的实践,第二种方式顺利搞定。毕竟lua源码中的README和INSTALL文档已经把编译lua讲的很明白了。
至于这第一种方式,别看书里一笔带过,这实践起来还真是。。。。。。 一言不合就翻车了。
...
阅读全文 ...
31 May 2016
自从13年开始做手游接触lua,始终是边写边学,缺乏对lua更加全面系统的学习,这几篇文章开始“重识lua”, 把欠下的帐还回来。这个系列侧重于总结lua作为扩展程序的用法,不会着重介绍lua的语法。
前言
本文介绍如何在C++中调用lua的function,lua很多情况下是被用做一种扩展语言,它的function更是增加了这门扩展语言的灵活性,赋予了lua生命力,使它变化莫测。在lua的function中还可以回调宿主语言的函数。这篇文章展示如何从C++端调用lua函数,相反的过程在后面的文章再做介绍。
本文使用的Lua版本还是5.1。
简单的调用示例
还是使用上一篇文章中使用的环境,调用config.lua里面的f函数:
res/config.lua:
function f ( var )
return var * var + 2 * var + 100
end
...
阅读全文 ...
30 May 2016
自从13年开始做手游接触lua,始终是边写边学,缺乏对lua更加全面系统的学习,这几篇文章开始“重识lua”, 把欠下的帐还回来。这个系列侧重于总结lua作为扩展程序的用法,不会着重介绍lua的语法。
前言
前一篇文章总结了lua中C API的基本用法和常见的虚拟栈操作函数,并没有涉及到具体的lua代码,只有当这些API用来连接lua代码和C++代码的时候,才能发挥出它的最大威力。本文的主题在于使用C++来加载、调用lua代码。
本文使用的Lua版本还是5.1。
C++中加载lua脚本
就像打开其它类型的文件一样,比如打开一个txt文件读取成一个字符串,打开一个json文件用json解析库来解析出感兴趣的字段;对于lua脚本则有lua解析器去解释它,它不仅可以被当做普通的静态配置文件来使用,更牛的地方就在于,它,是可编程的!对,因为它是一门编程语言。尤其是当你为lua打开了它的翅膀(lua标准库)。
下面就给出一个简单的例子,演示一下,如何把lua脚本当做一种资源,载入到C++代码中。
下面这个lua文件里定义了两个全局变量一个是字符串类型的怪物类型,一个是怪物血量,我把它当做一个配置文件来用,在C++中读取它们的值
res/config.lua:
monster_type = "Ghost"
blood = 99 . 9
main.cpp:
#include "lua_51/lua.hpp"
#include "include/inc.h"
#include <string>
using namespace elloop ;
using namespace std ;
int main () {
string scriptName ( "res/config.lua" );
lua_State * lua = luaL_newstate ();
int luaError = luaL_loadfile ( lua , scriptName . c_str ()); // 加载lua文件
if ( luaError ) {
error ( lua , "fail to load script: %s, %s" , scriptName . c_str (), lua_tostring ( lua , - 1 ));
}
luaError = lua_pcall ( lua , 0 , 0 , 0 ); // 执行这个lua文件, 三个0依次表示:输入0个参数,返回0个结果,需要0个错误处理函数
if ( luaError ) {
error ( lua , "fail to run script: %s" , lua_tostring ( lua , - 1 ));
}
lua_getglobal ( lua , "blood" ); // 获取全局变量blood
lua_getglobal ( lua , "monster_type" ); // 获取全局变量monster_type
double blood = lua_tonumber ( lua , 1 ); // 读取两个全局变量
const char * type = lua_tostring ( lua , 2 );
psln ( blood ); // 打印 blood = 99.9
psln ( type ); // type = Ghost
lua_close ( lua );
return 0 ;
}
...
阅读全文 ...
29 May 2016
自从13年开始做手游接触lua,始终是边写边学,缺乏对lua更加全面系统的学习,这几篇文章开始“重识lua”, 把欠下的帐还回来。这个系列侧重于总结lua作为扩展程序的用法,不会着重介绍lua的语法。
前言
本文总结了Lua中操作虚拟栈的API,通过这些API可以做到在Lua和C/C++之间传递数据,相互调用对方。在Programming In Lua那本书中(后文简称PIL),作者把这些API称作“C API”,一方面是因为他们是用C语言实现,另一方面它们的作用是用来实现C/C++语言和Lua之间的相互调用。正如PIL中说的那样,几乎所有的这些API都会操作虚拟栈,这个虚拟栈在C/C++与Lua通信过程中,解决了两者之间存在的两个差异,第一是内存管理方式的差异:Lua的垃圾回收和C语言的手动管理;第二是数据类型方面的差异:Lua是动态类型和C语言的静态类型。
本文使用的Lua版本还是5.1。
Lua C API 版Hello World
下面这段代码演示了C API的基本用法,向lua虚拟栈中push了一个字符串,然后从栈中读取这个字符串,将其打印出来:
extern "C" {
#include "lua_51/lua.h" // C API函数声明所在的文件
#include "lua_51/lauxlib.h" // luaL_ 开头的函数所在的头文件, 比如luaL_newstate
}
#include <iostream>
int main ()
{
lua_State * lua = luaL_newstate (); // 创建一个lua state
lua_pushstring ( lua , "hello world" ); // 入栈一个字符串
std :: cout << lua_tostring ( lua , 1 ) << std :: endl ; // 从栈中读取字符串
lua_close ( lua ); // 关闭lua state
return 0 ;
}
...
阅读全文 ...