-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
522 lines (414 loc) · 106 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>骑士之花</title>
<subtitle>随想录</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="www.qqshark.com/"/>
<updated>2017-09-10T10:59:49.000Z</updated>
<id>www.qqshark.com/</id>
<author>
<name>Shicai Xu</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>golang调用c动态库</title>
<link href="www.qqshark.com/2017/09/10/golang%E8%B0%83%E7%94%A8%E5%8A%A8%E6%80%81%E5%BA%93/"/>
<id>www.qqshark.com/2017/09/10/golang调用动态库/</id>
<published>2017-09-10T09:07:16.000Z</published>
<updated>2017-09-10T10:59:49.000Z</updated>
<content type="html"><![CDATA[<p>golang以其高并发,部署简单,编译迅速,而且像动态语言一样的开发效率等特点,吸引了很多程序的关注,但是有时候为了运行速度需要跟c一起使用,现整理一个golang调用c动态链接库的demo程序,以供自己将来参考,以下文字,大多来源于网络,整理如下。</p>
<a id="more"></a>
<ol>
<li><p>创建项目</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">../cgolearn</div><div class="line">├── lib</div><div class="line">│ ├── test_so.c</div><div class="line">│ └── test_so.h</div><div class="line">└── src</div><div class="line"> ├── load_so.c</div><div class="line"> ├── load_so.h</div><div class="line"> └── main.go</div></pre></td></tr></table></figure>
</li>
<li><p>创建动态连接库</p>
<p> lib目录下文件内容如下:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//test_so.h</span></div><div class="line"></div><div class="line"><span class="keyword">int</span> test_so_func(<span class="keyword">int</span> a,<span class="keyword">int</span> b);</div></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//test_so.c</span></div><div class="line"></div><div class="line">#include <span class="string">"test_so.h"</span></div><div class="line"></div><div class="line"><span class="keyword">int</span> test_so_func(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</div><div class="line">{</div><div class="line"> <span class="keyword">return</span> a*b;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 生成so文件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> lib</div><div class="line">gcc -shared ./test_so.c -o test_so.so</div></pre></td></tr></table></figure>
</li>
<li><p>在golang代码中调用c动态库函数<br> src目录下文件内容如下:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//load_so.h</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">do_test_so_func</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span></span>;</div></pre></td></tr></table></figure>
<figure class="highlight c"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//load_so.c</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"load_so.h"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><dlfcn.h></span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">do_test_so_func</span><span class="params">(<span class="keyword">int</span> a,<span class="keyword">int</span> b)</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="keyword">void</span>* handle;</div><div class="line"> <span class="function"><span class="keyword">typedef</span> <span class="title">int</span> <span class="params">(*FPTR)</span><span class="params">(<span class="keyword">int</span>,<span class="keyword">int</span>)</span></span>;</div><div class="line"></div><div class="line"> handle = dlopen(<span class="string">"../lib/test_so.so"</span>, <span class="number">1</span>);</div><div class="line"> FPTR fptr = (FPTR)dlsym(handle, <span class="string">"test_so_func"</span>);</div><div class="line"></div><div class="line"> <span class="keyword">int</span> result = (*fptr)(a,b);</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//main.go</span></div><div class="line"></div><div class="line"><span class="keyword">package</span> main</div><div class="line"></div><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment">#include "load_so.h"</span></div><div class="line"><span class="comment">#cgo LDFLAGS: -ldl</span></div><div class="line"><span class="comment">*/</span></div><div class="line"><span class="keyword">import</span> <span class="string">"C"</span></div><div class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</div><div class="line"> fmt.Println(<span class="string">"20*30="</span>, C.do_test_so_func(<span class="number">20</span>, <span class="number">30</span>))</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 编译运行:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> src</div><div class="line">go build -o main</div><div class="line">./main</div></pre></td></tr></table></figure>
</li>
<li><p>注意事项<br> 1,import “C”,一定要紧跟着cgo标志的注释代码,中间不能有空行。<br> 2,import “C”必须单独一行,不能和其它库一起导入。</p>
</li>
<li><p>待做事项<br> do_test_so_func可以优化成一个工厂函数,从Go代码中传入不同的标志,调用不同的函数,返回不同类型的返回值。或者创建一个函数映射表来调用。</p>
</li>
</ol>
]]></content>
<summary type="html">
<p>golang以其高并发,部署简单,编译迅速,而且像动态语言一样的开发效率等特点,吸引了很多程序的关注,但是有时候为了运行速度需要跟c一起使用,现整理一个golang调用c动态链接库的demo程序,以供自己将来参考,以下文字,大多来源于网络,整理如下。</p>
</summary>
<category term="go" scheme="www.qqshark.com/categories/go/"/>
<category term="go" scheme="www.qqshark.com/tags/go/"/>
<category term="c" scheme="www.qqshark.com/tags/c/"/>
</entry>
<entry>
<title>服务端程序员常见面试问题整理</title>
<link href="www.qqshark.com/2017/09/05/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%A8%8B%E5%BA%8F%E5%91%98%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/"/>
<id>www.qqshark.com/2017/09/05/服务端程序员常见面试问题整理/</id>
<published>2017-09-05T09:53:04.000Z</published>
<updated>2017-09-10T10:07:39.000Z</updated>
<content type="html"><![CDATA[<p>程序员的日常工作,就像搭积木,编程语言,数据库,常用开发框架等,都是积木的一块,程序员就是阅读说明书,把这些积木配合起来,做成一个软件,所以程序员经常自嘲为码农。 常见的面试问题,大多都偏理论,就像你会用积木搭建一栋房子,突然有人问你,你知道积木是怎么做的吗?此时一脸懵逼。很多时候,知道有那么回事儿,但是概念并不清晰,现在自己整理下自己遇见的面试问题,希望以后避免懵逼的尴尬。</p>
<a id="more"></a>
<ol>
<li><p>Python的GIL</p>
<p>在python的原始解释器CPython中存在着GIL(Global Interpreter Lock,全局解释器锁),因此在解释执行python代码时,会产生互斥锁来限制线程对共享资源的访问,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL。所以,虽然CPython的线程库直接封装了系统的原生线程,但CPython整体作为一个进程,同一时间只会有一个获得GIL的线程在跑,其他线程则处于等待状态。这就造成了即使在多核CPU中,多线程也只是做着分时切换而已。这也是GIL饱受诟病的原因。</p>
<p>Python 不适合开发 CPU 密集型的程序, Python 多线程的意义就是能让每条语句宏观上并发执行。对于 IO 密集型的程序,Python 多线程还是有很大作用的。然而 Python 3 引入的 asyncio 模块使得很多 IO 操作有了更好的方式去解决,这就非常类似 Node.js 了,都是没有多线程,而是采用 Event Loop 来处理耗时的 IO 操作。</p>
<p>muiltprocessing库,也可以让多进程的python代码编写类似多线程。</p>
</li>
<li><p>进程、线程和协程的理解<br> 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。</p>
<p> 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。</p>
<p> 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。如果使用封装好的,例如gevent等协程库,程序员就不必承担调度的责任。</p>
<p> 其他参考:<br> <a href="http://www.jianshu.com/p/f11724034d50" target="_blank" rel="external">进程,线程,协程与并行,并发</a><br> <a href="http://www.cnblogs.com/guokaixin/p/6041237.html" target="_blank" rel="external">进程线程协程的区别</a></p>
</li>
<li><p>TCP与UDP区别总结<br>1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接<br>2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付<br>3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的<br>UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)<br>4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信<br>5、TCP首部开销20字节;UDP的首部开销小,只有8个字节<br>6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">tcp协议和udp协议的差别 </div><div class="line"> TCP UDP </div><div class="line">是否连接 面向连接 面向非连接 </div><div class="line">传输可靠性 可靠 不可靠 </div><div class="line">应用场合 传输大量数据 少量数据 </div><div class="line">速度 慢 快</div></pre></td></tr></table></figure>
</li>
<li><p>待续</p>
</li>
</ol>
]]></content>
<summary type="html">
<p>程序员的日常工作,就像搭积木,编程语言,数据库,常用开发框架等,都是积木的一块,程序员就是阅读说明书,把这些积木配合起来,做成一个软件,所以程序员经常自嘲为码农。 常见的面试问题,大多都偏理论,就像你会用积木搭建一栋房子,突然有人问你,你知道积木是怎么做的吗?此时一脸懵逼。很多时候,知道有那么回事儿,但是概念并不清晰,现在自己整理下自己遇见的面试问题,希望以后避免懵逼的尴尬。</p>
</summary>
<category term="面试" scheme="www.qqshark.com/categories/%E9%9D%A2%E8%AF%95/"/>
<category term="面试" scheme="www.qqshark.com/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>cocoscreator 1.5.2 热更新 大厅 + 子游戏 不用重启DEMO</title>
<link href="www.qqshark.com/2017/08/20/cocoscreator-hall-with-subgames-demo/"/>
<id>www.qqshark.com/2017/08/20/cocoscreator-hall-with-subgames-demo/</id>
<published>2017-08-20T15:11:02.000Z</published>
<updated>2017-09-04T15:21:00.000Z</updated>
<content type="html"><![CDATA[<center><br><a href="http://forum.cocos.com/t/1-5-2-demo/48200" target="_blank" rel="external">cocos论坛关于该话题讨论帖子的地址</a><br></center>
<p>大厅和子游戏均为正常cocos creater项目,只是热更新的时候指向的地址和本地保存的目录不一样。</p>
<a id="more"></a>
<center><br><a href="https://github.com/GeorgeValentin/cocoscreator_hall_with_subgames_demo" target="_blank" rel="external">Demo工程Github地址</a><br></center>
<ol>
<li><p>创建大厅项目 详细逻辑见 hall项目</p>
</li>
<li><p>创建子游戏项目 详细逻辑见 subgame项目</p>
<p> 注意:坑1,不要都创建helloworld,可以一个空项目,一个helloworld项目再修改,否则加载子游戏的时候会爆错 Class already exists with the same cid : “280c3rsZJJKnZ9RqbALVwtK”. 导致子游戏按钮点起来没反应!</p>
</li>
<li><p>打开webstorm创建一个express项目命名hotupdate,目的为托管热更新文件,也可以用其他web服务器。在hotupdate项目的public文件夹下创建remote-assets文件夹。</p>
</li>
<li><p>在subgame项目根目录下创建build-template/jsb-binary/src文件夹,新建main.js dating.js文件在此文件夹,具体代码参见对应文件,这样每次构建编译,ccc就会自动帮你拷贝到build文件夹下面对应路径。</p>
<p>用cocoscreater构建,编译subgame。</p>
<p>然后在subgame根目录下,执行命令: node version_generator.js -v 1.0.0 -u <a href="http://192.168.2.114:3000/remote-assets/subgame/" target="_blank" rel="external">http://192.168.2.114:3000/remote-assets/subgame/</a> -s build/jsb-binary -d remote-assets/ 生成子游戏的热更新文件。</p>
<p>拷贝build/js-binary下生成的res和src文件夹到 romote-assets文件夹。 此时,子游戏的所有热更新文件已经生成完毕。</p>
</li>
<li><p>拷贝subgam项目下romote-assets里面的所有文件到hotupdate项目下的public/romote-assets/subgame文件。</p>
<p> 注意:坑2,生成的project.manifest放到public/romote-assets/subgame要改名字,改成跟代码里对应的名字,只要不叫project.manifest就行,例如peision.manifest或则sub_game_project.manifest(此处可以修改version_generator.js脚本逻辑给其重命名,免掉手动修改的麻烦)否则每次重启APP都会清空本地下载的子游戏,导致再次进入不了,具体原因未知。</p>
<p> 启动hotupdate,在浏览器打开<a href="http://192.168.2.114:3000/remote-assets/subgame/version.manifest如果能看到正常的version.manifest内容说明,服务器搭建成功,热更新文件能正常访问。" target="_blank" rel="external">http://192.168.2.114:3000/remote-assets/subgame/version.manifest如果能看到正常的version.manifest内容说明,服务器搭建成功,热更新文件能正常访问。</a></p>
</li>
<li><p>此时运行hall,点击下载游戏,下载完成之后,点击进入游戏,点击返回大厅就能返回。到此,大厅加子游戏demo完成。 注意:坑3,在ccc自带的模拟器里面是不能返回大厅的,会报无法加载场景对应的json文件的错误。在xcode的模拟器里面没问题。</p>
<p> 注意:build-template里面的main.js 和 dating.js 每个子游戏都应该有一份,需要仔细规划一下,统一代码风格,和项目相关的一些变量。 同时需要注意这俩文件初始化资源目录的地方开头加斜杠和不叫斜杠的区别,前者去找默认的大厅项目资源,后者是去相对目录找资源。</p>
</li>
</ol>
]]></content>
<summary type="html">
<center><br><a href="http://forum.cocos.com/t/1-5-2-demo/48200" target="_blank" rel="external">cocos论坛关于该话题讨论帖子的地址</a><br></center>
<p>大厅和子游戏均为正常cocos creater项目,只是热更新的时候指向的地址和本地保存的目录不一样。</p>
</summary>
<category term="cocos creator" scheme="www.qqshark.com/categories/cocos-creator/"/>
<category term="cocos2dx" scheme="www.qqshark.com/tags/cocos2dx/"/>
<category term="cocos creator" scheme="www.qqshark.com/tags/cocos-creator/"/>
</entry>
<entry>
<title>微信小程序开发环境配置笔记</title>
<link href="www.qqshark.com/2017/01/17/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E7%AC%94%E8%AE%B0/"/>
<id>www.qqshark.com/2017/01/17/微信小程序开发环境配置笔记/</id>
<published>2017-01-17T02:22:24.000Z</published>
<updated>2017-09-04T03:03:35.000Z</updated>
<content type="html"><![CDATA[<p><center>微信小程序开发环境配置, Nginx需要开启https, 申请ssl证书</center><br><a id="more"></a></p>
<ol>
<li><p>调试时可以直接用内网<br><a href="http://ip:port/api/a/b?args={}&sig=xxxx" target="_blank" rel="external">http://ip:port/api/a/b?args={}&sig=xxxx</a><br>进行联网</p>
</li>
<li><p>开发时小程序后台配置<br>项目-开发环境不校验请求域以及TLS版本 去掉勾选不验证域名</p>
</li>
<li><p>上传时,需要在微信小程序后台,设置,开发设置添加校验域名,<br>注意:不要带www,例如 <a href="https://wjdc.xxx.com" target="_blank" rel="external">https://wjdc.xxx.com</a></p>
</li>
<li><p>服务器需要搭建https环境</p>
<ol>
<li>nginx开启https<br>命令行 nginx -V 查看nginx是否开启了–with-http_ssl_module选项,如果没有,需要重新编译带上此选项</li>
<li>申请ssl证书<br>去阿里云申请ssl证书,有免费试用一年的。<br>服务器是阿里云的,推荐DNS类证书,注意对应域名不要带www,例如wjdc.xxx.com,否则会提示服务器被冒充,勾选自动创建主机记录和记录值,审核完毕后下载证书,解压到nginx.conf同级的cert目录下<br>然后修改nginx.conf<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line">server {</div><div class="line"> listen 443;</div><div class="line"> server_name wjdc.knightflower.com;</div><div class="line"></div><div class="line"> charset utf-8;</div><div class="line"> access_log /data/wjdc/logs/https_access.log main;</div><div class="line"></div><div class="line"> ssl on;</div><div class="line"> ssl_certificate cert/xxx.pem;</div><div class="line"> ssl_certificate_key cert/xxx.key;</div><div class="line"> ssl_session_timeout 5m;</div><div class="line"> ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;</div><div class="line"> ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</div><div class="line"> ssl_prefer_server_ciphers on;</div><div class="line"></div><div class="line"> location / {</div><div class="line"> try_files /_not_exists_ @backend;</div><div class="line"> }</div><div class="line"></div><div class="line"> location @backend {</div><div class="line"> proxy_set_header X-Forwarded-For $remote_addr;</div><div class="line"> proxy_set_header Host $http_host;</div><div class="line"></div><div class="line"> proxy_pass http://127.0.0.1:6066;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ol>
</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">nginx -t -c /etc/nginx/nginx.conf <span class="comment">#校验配置文件是否有错</span></div><div class="line">nginx -s reload <span class="comment">#重新加载配置文件</span></div></pre></td></tr></table></figure>
<p>然后就可以在小程序里面用wx.request接口请求服务器,url:”<a href="https://wjdc.xxx.com/a/q/query" target="_blank" rel="external">https://wjdc.xxx.com/a/q/query</a>“</p>
]]></content>
<summary type="html">
<p><center>微信小程序开发环境配置, Nginx需要开启https, 申请ssl证书</center><br>
</summary>
<category term="小程序" scheme="www.qqshark.com/categories/%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
<category term="nginx" scheme="www.qqshark.com/tags/nginx/"/>
<category term="https" scheme="www.qqshark.com/tags/https/"/>
</entry>
<entry>
<title>cocos2dx 3.13.1 jsbinding 测试记录</title>
<link href="www.qqshark.com/2016/11/16/cocos2dx-3-13-1-jsbinding-%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95/"/>
<id>www.qqshark.com/2016/11/16/cocos2dx-3-13-1-jsbinding-测试记录/</id>
<published>2016-11-16T03:08:33.000Z</published>
<updated>2017-09-04T03:25:40.000Z</updated>
<content type="html"><![CDATA[<center><br>cocos2dx 3.13.1 jsbinding 测试记录<br></center>
<a id="more"></a>
<ol>
<li><p>cocos new -p com.mz.jsbtest -d ./ -l js JSBTest</p>
</li>
<li><p>在cocos2dx/cocos目录新建目录my 增加类文件</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//CustomClass.hpp</span></div><div class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> CustomClass_hpp</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> CustomClass_hpp</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"cocos2d.h"</span></span></div><div class="line">USING_NS_CC;</div><div class="line"><span class="keyword">namespace</span> cocos2d {</div><div class="line"> <span class="class"><span class="keyword">class</span> <span class="title">CustomClass</span> :</span> <span class="keyword">public</span> cocos2d::Ref</div><div class="line"> {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> </div><div class="line"> CustomClass();</div><div class="line"> </div><div class="line"> ~CustomClass();</div><div class="line"> </div><div class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">init</span><span class="params">()</span></span>;</div><div class="line"> </div><div class="line"> <span class="built_in">std</span>::<span class="function"><span class="built_in">string</span> <span class="title">helloMsg</span><span class="params">()</span></span>;</div><div class="line"> </div><div class="line"> CREATE_FUNC(CustomClass);</div><div class="line"> };</div><div class="line">} <span class="comment">//namespace cocos2d</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* CustomClass_hpp */</span></span></div></pre></td></tr></table></figure>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//CustomClass.cpp</span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"CustomClass.hpp"</span></span></div><div class="line"></div><div class="line">USING_NS_CC;</div><div class="line"></div><div class="line">CustomClass::CustomClass(){</div><div class="line"> </div><div class="line">}</div><div class="line"></div><div class="line">CustomClass::~CustomClass(){</div><div class="line"> </div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">bool</span> CustomClass::init(){</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">std</span>::<span class="built_in">string</span> CustomClass::helloMsg() {</div><div class="line"> <span class="keyword">return</span> <span class="string">"Hello from CustomClass::sayHello"</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>在cocos2dx/tools/tojs 目录下新增cocos2dx_custom.ini配置文件用于描述绑定的名字空间,前缀等信息,如果提示错误尽量参考tojs目录下的其他ini文件的格式如cocos2dx_builder.ini,不同cocos2dx版本之间语法貌似有差异,注意这里我们新增的类继承了Ref类,所以base_classes_to_skip = Ref,否则会提示Ref x86_64未定义啥的,如果是纯是自己写的类就不用了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line">[cocos2dx_custom]</div><div class="line">name = cocos2dx_custom</div><div class="line">prefix = cocos2dx_custom</div><div class="line">target_namespace = cc</div><div class="line"></div><div class="line">headers = %(cocosdir)s/cocos/my/CustomClass.hpp</div><div class="line">classes = CustomClass</div><div class="line"></div><div class="line">android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.9/include</div><div class="line">android_flags = -D_SIZE_T_DEFINED_ </div><div class="line"></div><div class="line">clang_headers = -I%(clangllvmdir)s/%(clang_include)s </div><div class="line">clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__</div><div class="line"></div><div class="line">cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/external</div><div class="line"></div><div class="line">cocos_flags = -DANDROID</div><div class="line"></div><div class="line">extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s </div><div class="line"></div><div class="line">classes_have_type_info = no</div><div class="line"></div><div class="line"># base classes which will be skipped when their sub-classes found them.</div><div class="line">base_classes_to_skip = Ref</div><div class="line"></div><div class="line"># Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.</div><div class="line">script_control_cpp = yes</div></pre></td></tr></table></figure>
</li>
<li><p>在tojs目录下,修改执行genbindings.py文件尽量注释掉cmd_args中cocos2dx自带的那些绑定,再加入自己定制的绑定,否则容易出错,就呆重新建项目, 然后执行python genbindings.py<br>也可以加在custom_cmd_args里面会生成到cocos2dx/frameworks/custome/auto,不过目录处理起来比较麻烦</p>
</li>
<li>生成的代码在cocos2dx/cocos/scripting/js-bindings/auto下面,加入Xcode中的cocos2d_js_bindings.xcodeproj<br>my目录加到头文件搜索路径</li>
<li><p>在AppDelegate.cpp引入生成的头文件</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"scripting/js-bindings/auto/jsb_cocos2dx_custom.hpp"</span></span></div></pre></td></tr></table></figure>
<p> 在applicationDidFinishLaunching函数加入<br> sc->addRegisterCallback(register_all_cocos2dx_custom);<br> 然后就可以在app.js中调用我们绑定的代码了</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">var customClass = cc.CustomClass.create();</div><div class="line">var msg = customClass.helloMsg()</div><div class="line">cc.<span class="built_in">log</span>(<span class="string">"customClass's msg is : "</span> + msg)</div></pre></td></tr></table></figure></li>
</ol>
]]></content>
<summary type="html">
<center><br>cocos2dx 3.13.1 jsbinding 测试记录<br></center>
</summary>
<category term="cocos2dx" scheme="www.qqshark.com/categories/cocos2dx/"/>
<category term="cocos2dx" scheme="www.qqshark.com/tags/cocos2dx/"/>
<category term="jsb" scheme="www.qqshark.com/tags/jsb/"/>
</entry>
<entry>
<title>从论坛下载的老版本cocos2dx项目怎么运行</title>
<link href="www.qqshark.com/2016/10/19/%E4%BB%8E%E8%AE%BA%E5%9D%9B%E4%B8%8B%E8%BD%BD%E7%9A%84%E8%80%81%E7%89%88%E6%9C%ACcocos2dx%E9%A1%B9%E7%9B%AE%E6%80%8E%E4%B9%88%E8%BF%90%E8%A1%8C/"/>
<id>www.qqshark.com/2016/10/19/从论坛下载的老版本cocos2dx项目怎么运行/</id>
<published>2016-10-19T02:46:59.000Z</published>
<updated>2017-09-04T03:04:54.000Z</updated>
<content type="html"><![CDATA[<p>从论坛下载的cocos2dx项目,需要研究其逻辑,或者做二次开发,经常发现不能直接运行,以下是一些经验性的解决方法。</p>
<a id="more"></a>
<p>从网上下载的cocos2dx项目运行或升级步骤:</p>
<ol>
<li>下载xxx.zip文件,解压</li>
<li>若是3.x的可以直接运行,2.x的如果不带库文件不能直接运行,需要放到cocos2dx-2.x.x的projects目录下面运行测试</li>
<li>如果放到projects文件夹下面可以正常运行,则进入如下步骤:<ol>
<li>创建SVN目录树</li>
<li>将项目放入trunk目录</li>
<li>将cocos2dx引擎的四个文件夹 coco2dx CocosDenshion extensions external 拷贝到trunk目录</li>
<li>打开 ios项目文件 修改项目目录树里面的cocos2dx.xcodeproj Box2d chipmunk CocosDenshion extensions libwebsocket 指向的上述拷贝过来的对应文件夹</li>
<li>修改项目 build setting-> search paths 改为当前相对目录,如上即使依次删除 header search paths和library search paths 各个路径的“../../”</li>
<li>修改build phases->link binary with libraries 增加libcocos2dx.a</li>
<li>打开mac版项目文件 做上述同样步骤的修改</li>
<li>Android项目修改对应的 Android.mk文件索引对应的代码文件,build_native.sh修改COCOS2DX_ROOT</li>
</ol>
</li>
</ol>
<p>osx系统升级,会遇到cocos2dx 2.x项目 如果遇到<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">m_pValueDict->setObject( CCString::create( (<span class="keyword">const</span> <span class="keyword">char</span>*)glGetString(GL_VENDOR)), <span class="string">"gl.vendor"</span>);</div></pre></td></tr></table></figure></p>
<p>报错</p>
<p>修改 mac项目的 AppController.mm文件的 applicationDidFinishLaunching函数<br>在<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">glView = [[EAGLView alloc] initWithFrame:rect pixelFormat:pixelFormat];</div></pre></td></tr></table></figure></p>
<p>下面加入<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[glView prepareOpenGL];</div></pre></td></tr></table></figure></p>
<p>方案一:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">NSOpenGLContext</span> *ctx = [[<span class="built_in">NSOpenGLContext</span> alloc] initWithFormat:pixelFormat shareContext:<span class="literal">nil</span>];</div><div class="line"><span class="keyword">if</span>(ctx)</div><div class="line">{</div><div class="line"> [glView setOpenGLContext:ctx];</div><div class="line"> [ctx setView:glView];</div><div class="line"> [ctx makeCurrentContext];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>方案二:<br><figure class="highlight objc"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[glView prepareOpenGL];</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<p>从论坛下载的cocos2dx项目,需要研究其逻辑,或者做二次开发,经常发现不能直接运行,以下是一些经验性的解决方法。</p>
</summary>
<category term="cocos2dx" scheme="www.qqshark.com/categories/cocos2dx/"/>
<category term="cocos2dx" scheme="www.qqshark.com/tags/cocos2dx/"/>
<category term="oc" scheme="www.qqshark.com/tags/oc/"/>
</entry>
<entry>
<title>用lua 5.2为c++创建动态链接库</title>
<link href="www.qqshark.com/2014/09/07/CREATING-A-LUA-5-2-DYNAMIC-LINK-LIBRARY-OF-Cpp-FUNCTIONS/"/>
<id>www.qqshark.com/2014/09/07/CREATING-A-LUA-5-2-DYNAMIC-LINK-LIBRARY-OF-Cpp-FUNCTIONS/</id>
<published>2014-09-07T14:12:49.000Z</published>
<updated>2017-09-04T14:55:10.000Z</updated>
<content type="html"><![CDATA[<p>原文链接:<a href="http://www.acamara.es/blog/2012/08/creating-a-lua-5-2-dynamic-link-library-of-c-functions/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/creating-a-lua-5-2-dynamic-link-library-of-c-functions/</a></p>
<p>我的译文如下:</p>
<p>欢迎惠阅我的第四篇c++和Lua5.2混编的学习笔记。如果你还没读过我的前三篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>, <a href="/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/">从lua脚本中向c++传递变量</a>, <a href="/2014/08/01/CALLING-Cpp-FUNCTIONS-FROM-LUA-5-2/">在lua中调用c++函数</a>。</p>
<p>本篇新教程将讲述如何创建c动态链接库,以及如何在Lua5.2中使用它们。<br>我将假设你已经懂得怎么创建动态链接库。本文代码将在通过Mac osx10.8.4, gcc4.8进行编译。你可以略做修改转换编译器,然后运行到其他系统。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。</p>
<a id="more"></a>
<h4 id="本文目的"><a href="#本文目的" class="headerlink" title="本文目的"></a>本文目的</h4><p>假设你已经有一些有用的并且能和Lua5.2适配的c或者c++函数(记住必须是lua_CFunction类型的函数哦)。为了重用代码,你希望将它们打包成库,然后再需要的时候动态链接。就如同你使用Lua标准库一样。<br>Lua标准库中有io, string, table等等,在需要的时候可以加载它们。</p>
<p>本文,我们将学习怎样创建C语言动态链接库,并在Lua中调用它们。</p>
<p>由于本文使用的c++代码基本与前文一致,所以就省略不写了。但是会展示简短的Lua代码以便更好的理解程序的输出结果,以及将要创建C语言动态链接库的c++代码。<br>你可以从个链接下载这三部分代码。</p>
<h4 id="Lua脚本部分"><a href="#Lua脚本部分" class="headerlink" title="Lua脚本部分"></a>Lua脚本部分</h4><p>Lua脚本将动态的链接我们的新的库,其名字为cfunctions。<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment">-- load the c-function library</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Loading the C-function libraryn"</span>)</div><div class="line">cfunctions = <span class="built_in">require</span>(<span class="string">"cfunctions"</span>)</div><div class="line"></div><div class="line"><span class="comment">-- use some of the functions defined in the library</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Executing the C-library functionsn"</span>);</div><div class="line"><span class="keyword">local</span> f = cfunctions.fun1()</div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Function 1 says it's "</span>, f, <span class="string">" times funnyn"</span>); </div><div class="line">f = cfunctions.fun2()</div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Function 2 says it's "</span>, f, <span class="string">" times funnyn"</span>); </div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Exiting Lua scriptn"</span>)</div></pre></td></tr></table></figure></p>
<p>库文件代码如下:<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream> </span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><lua.hpp></span></span></div><div class="line"></div><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> * Library functions</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="keyword">extern</span> <span class="string">"C"</span></div><div class="line">{</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">int</span> funval = <span class="number">10</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">function_1</span><span class="params">(lua_State* l)</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[DLL] Function 1 is very funny."</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[DLL] It's fun value is: "</span> << funval << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_pushnumber(l, funval);</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">function_2</span><span class="params">(lua_State* l)</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[DLL] Function 2 is twice as funny!"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[DLL] It's fun value is: "</span> << <span class="number">2</span>*funval << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_pushnumber(l, <span class="number">2</span>*funval);</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> * Registering functions</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">luaL_Reg</span> <span class="title">cfunctions</span>[] = {</span></div><div class="line"> {<span class="string">"fun1"</span>, function_1},</div><div class="line"> {<span class="string">"fun2"</span>, function_2},</div><div class="line"> {<span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">int</span> __declspec(dllexport) luaopen_cfunctions(lua_State* l)</div><div class="line">{</div><div class="line"> luaL_newlibtable(l, cfunctions);</div><div class="line"> luaL_setfuncs(l, cfunctions, <span class="number">0</span>);</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">}</div><div class="line">} <span class="comment">// end extern "C"</span></div></pre></td></tr></table></figure></p>
<h4 id="细节分析"><a href="#细节分析" class="headerlink" title="细节分析"></a>细节分析</h4><p>用于产生动态链接库的代码包含一个导出函数luaopen_cfunctions()和两个隐藏的函数function_1(),function_2()。导出函数会将两个隐藏函数注册到Lua。这样,就不能从外部直接调用它们了。</p>
<p>为了注册该库,我们首先创建一个带有需要注册函数的信息的结构体。在我们的例子中就是luaL_Reg结构体的数组cfunctions:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">luaL_Reg</span> <span class="title">cfunctions</span>[] = {</span></div><div class="line"> {<span class="string">"fun1"</span>, function_1},</div><div class="line"> {<span class="string">"fun2"</span>, function_2},</div><div class="line"> {<span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line">};</div></pre></td></tr></table></figure>
<p>需要说明的时,此例中在Lua将用fun1,fun2分别代替function_1,function_2。然后用luaL_newlibtable()在堆栈顶部创建library table,并用luaL_setfuncs()注册我们的函数。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">luaL_newlibtable(l, cfunctions);</div><div class="line">luaL_setfuncs(l, cfunctions, <span class="number">0</span>);</div></pre></td></tr></table></figure>
<p>最后,返回加入堆栈的元素个数,只有一个,就是我们的library table。</p>
<h4 id="咦,怎么报错了!!!"><a href="#咦,怎么报错了!!!" class="headerlink" title="咦,怎么报错了!!!"></a>咦,怎么报错了!!!</h4><p>可能有许多种原因,据我所知主要有以下两种:</p>
<p>如果报错信息是“The specified procedure could not be found”(找不到指定的程序)就很容易解决。我认为弹出这个错误的原因主要有两个:</p>
<h5 id="其一,你忘记了用extern-C-语句包含库文件代码。"><a href="#其一,你忘记了用extern-C-语句包含库文件代码。" class="headerlink" title="其一,你忘记了用extern C 语句包含库文件代码。"></a>其一,你忘记了用extern C 语句包含库文件代码。</h5><p>Lua底层用的是C语言,不能被c++链接。所以要告诉编译器用C语言的编译规则去编译库文件。解决方法就是用extern C包含你的库代码。</p>
<h5 id="其二,你忘记了导出你的函数。"><a href="#其二,你忘记了导出你的函数。" class="headerlink" title="其二,你忘记了导出你的函数。"></a>其二,你忘记了导出你的函数。</h5><p>即调用luaopen_cfunctions()声明你要导出的函数。在微软的编译器上,你还必须早导出函数前面加上__declspecs(dllexport)宏,<br>在其他的编译器上,仅仅定义为extern函数就行了。否则,你就是把自己的函数隐藏了,当然,编译器不会给你好脸色的。</p>
<p>如果报错信息是“Multiple Lua VMs detected”(检测到多个Lua虚拟机),说明你遇到了很隐蔽的错误。哥只有一个Lua状态机,所以第一次看到这个错误信息,哥被迷惑了。<br>你不能在Lua里面同时静态链接c++宿主程序和C库,你必须动态的往Lua库中链接它们。至少我这样解决了这个问题。</p>
<p>以上。</p>
<p>希望你已经学会怎么创建C函数库,并能通过require()函数动态的链接到Lua5.2。这与在c++中注册函数供Lua使用,并没有什么不同,但是却能大大提高代码的重用率。</p>
<p>稍后将奉上在c++和Lua中互传对象的教程,也即是我们的最终教程。敬请期待。</p>
]]></content>
<summary type="html">
<p>原文链接:<a href="http://www.acamara.es/blog/2012/08/creating-a-lua-5-2-dynamic-link-library-of-c-functions/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/creating-a-lua-5-2-dynamic-link-library-of-c-functions/</a></p>
<p>我的译文如下:</p>
<p>欢迎惠阅我的第四篇c++和Lua5.2混编的学习笔记。如果你还没读过我的前三篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>, <a href="/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/">从lua脚本中向c++传递变量</a>, <a href="/2014/08/01/CALLING-Cpp-FUNCTIONS-FROM-LUA-5-2/">在lua中调用c++函数</a>。</p>
<p>本篇新教程将讲述如何创建c动态链接库,以及如何在Lua5.2中使用它们。<br>我将假设你已经懂得怎么创建动态链接库。本文代码将在通过Mac osx10.8.4, gcc4.8进行编译。你可以略做修改转换编译器,然后运行到其他系统。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。</p>
</summary>
<category term="lua" scheme="www.qqshark.com/categories/lua/"/>
<category term="lua" scheme="www.qqshark.com/tags/lua/"/>
<category term="c++" scheme="www.qqshark.com/tags/c/"/>
</entry>
<entry>
<title>在lua中调用c++函数</title>
<link href="www.qqshark.com/2014/08/01/CALLING-Cpp-FUNCTIONS-FROM-LUA-5-2/"/>
<id>www.qqshark.com/2014/08/01/CALLING-Cpp-FUNCTIONS-FROM-LUA-5-2/</id>
<published>2014-08-01T13:55:04.000Z</published>
<updated>2017-09-01T14:21:15.000Z</updated>
<content type="html"><![CDATA[<p>原文出处:<a href="http://www.acamara.es/blog/2012/08/calling-c-functions-from-lua-5-2/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/calling-c-functions-from-lua-5-2/</a></p>
<p>我的译文如下:</p>
<p>欢迎惠阅我的第三篇Lua5.2的学习笔记。如果你还没读过我的前两篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>, <a href="/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/">从lua脚本中向c++传递变量</a>。</p>
<p>本篇新教程讲讲述如何在Lua5.2中给c++函数传递参数,并接收返回值。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。</p>
<p>嗯,我还是那个一如既往帅气阳光的基督小伙儿 Stigen Larsen。</p>
<p>首先,我将展示Lua和c++代码,以及其运行的输出结果。然后逐步剖析其中难点。</p>
<a id="more"></a>
<h4 id="Lua-脚本部分"><a href="#Lua-脚本部分" class="headerlink" title="Lua 脚本部分"></a>Lua 脚本部分</h4><p>Lua脚本将向c++函数传递一些参数,然后打印出c++返回的两个参数。<br>代码如下:</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">-- call the registered C-function</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">'[Lua] Calling the C functionn'</span>)</div><div class="line">a,b = displayLuaFunction(<span class="number">12</span>, <span class="number">3.141592</span>, <span class="string">'hola'</span>)</div><div class="line"></div><div class="line"><span class="comment">-- print the return values</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">'[Lua] The C function returned <'</span> .. a .. <span class="string">'> and <'</span> .. b .. <span class="string">'>n'</span>)</div></pre></td></tr></table></figure>
<h4 id="c-部分"><a href="#c-部分" class="headerlink" title="c++部分"></a>c++部分</h4><p>c++代码和前文基本一致。区别之处就是声明函数和将函数压入Lua堆栈的部分。<br>完整代码如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sstream></span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><lua.hpp></span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">displayLuaFunction</span><span class="params">(lua_State*)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>* argv[])</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="comment">// new Lua state</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Starting Lua state"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_State *lua_state = luaL_newstate();</div><div class="line"></div><div class="line"> <span class="comment">// load Lua libraries</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Loading Lua libraries"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">static</span> <span class="keyword">const</span> luaL_Reg lualibs[] = </div><div class="line"> {</div><div class="line"> {<span class="string">"base"</span>, luaopen_base},</div><div class="line"> {<span class="string">"io"</span>, luaopen_io},</div><div class="line"> {<span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line"> };</div><div class="line"> <span class="keyword">const</span> luaL_Reg *lib = lualibs;</div><div class="line"> <span class="keyword">for</span>(; lib->func != <span class="literal">NULL</span>; lib++)</div><div class="line"> {</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" loading '"</span> << lib->name << <span class="string">"'"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> luaL_requiref(lua_state, lib->name, lib->func, <span class="number">1</span>);</div><div class="line"> lua_settop(lua_state, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// push the C++ function to be called from Lua</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Pushing the C++ function"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_pushcfunction(lua_state, displayLuaFunction);</div><div class="line"> lua_setglobal(lua_state, <span class="string">"displayLuaFunction"</span>);</div><div class="line"></div><div class="line"> <span class="comment">// load the script</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Loading the Lua script"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">int</span> status = luaL_loadfile(lua_state, <span class="string">"parrotscript.lua"</span>);</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" return: "</span> << status << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"></div><div class="line"> <span class="comment">// run the script with the given arguments</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Running script"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">int</span> result = <span class="number">0</span>;</div><div class="line"> <span class="keyword">if</span>(status == LUA_OK)</div><div class="line"> {</div><div class="line"> result = lua_pcall(lua_state, <span class="number">0</span>, LUA_MULTRET, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span></div><div class="line"> {</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" Could not load the script."</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// close the Lua state</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Closing the Lua state"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">displayLuaFunction</span><span class="params">(lua_State *l)</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="comment">// number of input arguments</span></div><div class="line"> <span class="keyword">int</span> argc = lua_gettop(l);</div><div class="line"></div><div class="line"> <span class="comment">// print input arguments</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Function called from Lua with "</span> << argc </div><div class="line"> << <span class="string">" input arguments"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>; i<argc; i++)</div><div class="line"> {</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" input argument #"</span> << argc-i << <span class="string">": "</span></div><div class="line"> << lua_tostring(l, lua_gettop(l)) << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_pop(l, <span class="number">1</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// push to the stack the multiple return values</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Returning some values"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_pushnumber(l, <span class="number">12</span>);</div><div class="line"> lua_pushstring(l, <span class="string">"See you space cowboy"</span>);</div><div class="line"></div><div class="line"> <span class="comment">// number of return values</span></div><div class="line"> <span class="keyword">return</span> <span class="number">2</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="详细剖析"><a href="#详细剖析" class="headerlink" title="详细剖析"></a>详细剖析</h4><p>函数在Lua中是一等公民。这意味着Lua函数可以像普通变量一样存储。我们可以像对待普通变量一样把函数压入Lua堆栈,然后命名为全局变量。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// push the C++ function to be called from Lua</span></div><div class="line">lua_pushcfunction(lua_state, displayLuaFunction);</div><div class="line">lua_setglobal(lua_state, <span class="string">"displayLuaFunction"</span>);</div></pre></td></tr></table></figure></p>
<p>Lua就可以通过这个全局变量访问我们的函数displayLuaFunction()。除此之外,还有一个宏lua_register(),可以把上述步骤合二为一。<br>所以上述代码等价于:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// push the C++ function to be called from Lua</span></div><div class="line">lua_register(lua_state, <span class="string">"displayLuaFunction"</span>, displayLuaFunction);</div></pre></td></tr></table></figure>
<p>(感谢kpityu小伙儿在评论种指出这点)</p>
<p>为了便于c++和Lua交换数据,代码必须遵循一些规则。</p>
<h5 id="规则NO1:函数的定义和lua-CFunction一致"><a href="#规则NO1:函数的定义和lua-CFunction一致" class="headerlink" title="规则NO1:函数的定义和lua_CFunction一致"></a>规则NO1:函数的定义和lua_CFunction一致</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">typedef</span> <span class="title">int</span> <span class="params">(*lua_CFunction)</span> <span class="params">(lua_State *L)</span></span>;</div></pre></td></tr></table></figure>
<p>即函数必须接收指向lua_State的指针作为参数,并且返回整形。</p>
<h5 id="规则NO2-遵守Lua和c-交换数据的协议。"><a href="#规则NO2-遵守Lua和c-交换数据的协议。" class="headerlink" title="规则NO2:遵守Lua和c++交换数据的协议。"></a>规则NO2:遵守Lua和c++交换数据的协议。</h5><p>正如你所见,所有数据都是通过Lua堆栈作为桥梁交换的。<br>例如,当Lua调用c++函数时<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">displayLuaFunction(a, b, c)</div></pre></td></tr></table></figure></p>
<p>Lua会为此函数创建新的堆栈,该堆栈独立于其他堆栈。堆栈种包含输入参数,因此呢,我们在c++函数中可以通过Lua堆栈来获取所有参数。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// number of input arguments</span></div><div class="line"><span class="keyword">int</span> argc = lua_gettop(l);</div></pre></td></tr></table></figure></p>
<p>并且可以直接获取<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">lua_tostring(l, lua_gettop(l));</div></pre></td></tr></table></figure></p>
<p>需要注意的是,参数按传参顺序入栈,逆序出栈。由于一开始堆栈中只有输入参数,你可以直接通过索引获取其值。如果第二个参数可以被转化成字符串,我们可以这样获取它:<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">lua_tostring(l, <span class="number">2</span>);</div></pre></td></tr></table></figure></p>
<p>一旦该函数执行完毕,其返回值必须放入堆栈以便Lua使用它们。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// push to the stack the multiple return values</span></div><div class="line">lua_pushnumber(l, <span class="number">12</span>);</div><div class="line">lua_pushstring(l, <span class="string">"See you space cowboy"</span>);</div></pre></td></tr></table></figure></p>
<p>最后,为了让Lua能够获取c++回传的数据,我们需要返回放入Lua堆栈的变量的数量<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">// number of <span class="keyword">return</span> values</div><div class="line"><span class="keyword">return</span> <span class="number">2</span>;</div></pre></td></tr></table></figure></p>
<p>是的,就是这么简单!</p>
<p>此文讲述了Lua和c++混编的基本协议。如果想查看更多示例,请查阅Lua的相关库,它们都是严格遵循这些规则的。</p>
<p>我在犹豫,下篇文章是讨论Lua和c++混编时动态链接库的使用,还是讨论Lua和c++之间对象的传递呢,敬请期待。</p>
]]></content>
<summary type="html">
<p>原文出处:<a href="http://www.acamara.es/blog/2012/08/calling-c-functions-from-lua-5-2/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/calling-c-functions-from-lua-5-2/</a></p>
<p>我的译文如下:</p>
<p>欢迎惠阅我的第三篇Lua5.2的学习笔记。如果你还没读过我的前两篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>, <a href="/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/">从lua脚本中向c++传递变量</a>。</p>
<p>本篇新教程讲讲述如何在Lua5.2中给c++函数传递参数,并接收返回值。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。</p>
<p>嗯,我还是那个一如既往帅气阳光的基督小伙儿 Stigen Larsen。</p>
<p>首先,我将展示Lua和c++代码,以及其运行的输出结果。然后逐步剖析其中难点。</p>
</summary>
<category term="lua" scheme="www.qqshark.com/categories/lua/"/>
<category term="lua" scheme="www.qqshark.com/tags/lua/"/>
<category term="c++" scheme="www.qqshark.com/tags/c/"/>
</entry>
<entry>
<title>从lua脚本中向c++传递变量</title>
<link href="www.qqshark.com/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/"/>
<id>www.qqshark.com/2014/07/25/PASSING-VARIABLES-FROM-LUA-5-2-TO-Cpp/</id>
<published>2014-07-25T13:37:44.000Z</published>
<updated>2017-09-01T14:29:26.000Z</updated>
<content type="html"><![CDATA[<p>原文出处:<a href="http://www.acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/</a></p>
<p>我的译文如下</p>
<p>这是第二篇关于我和c++lua混编肉搏的笔记。如果你还没读过我的第一篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。<br>上篇文章仅仅只是抛砖引玉,c++和lua混编的强悍之处我们并未深入介绍。我希望通过以下示例让你能更进一步了解和使用lua.<br>我们的目标有两个:第一,从宿主语言c++往Lua脚本中传递参数。第二,从Lua脚本中接收返回数据。注意,Lua脚本可以返回不止一个数据哦!</p>
<a id="more"></a>
<h4 id="Lua脚本部分"><a href="#Lua脚本部分" class="headerlink" title="Lua脚本部分"></a>Lua脚本部分</h4><p>以下Lua脚本只是把我们存入全局的arg序列中的数据打印我们出来,然后返回不同类型Lua变量。<br>代码如下:</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="comment">-- print the arguments passed from C</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] These args were passed into the script from Cn"</span>)</div><div class="line"><span class="keyword">for</span> i=<span class="number">1</span>,#<span class="built_in">arg</span> <span class="keyword">do</span></div><div class="line"> <span class="built_in">print</span>(<span class="string">" "</span>, i, <span class="built_in">arg</span>[i])</div><div class="line"><span class="keyword">end</span> </div><div class="line"><span class="comment">-- return a value of different Lua types (boolean, table, numeric, string)</span></div><div class="line"><span class="built_in">io</span>.<span class="built_in">write</span>(<span class="string">"[Lua] Script returning data back to Cn"</span>)</div><div class="line"></div><div class="line"><span class="comment">-- create the table</span></div><div class="line"><span class="keyword">local</span> temp = {}</div><div class="line">temp[<span class="number">1</span>]=<span class="number">9</span></div><div class="line">temp[<span class="number">2</span>]=<span class="string">"See you space cowboy!"</span></div><div class="line"></div><div class="line"><span class="keyword">return</span> <span class="literal">true</span>,temp,<span class="number">21</span>,<span class="string">"I am a mushroom"</span></div></pre></td></tr></table></figure>
<p>为了在c++和Lua之间互传信息,我们必须编译c++程序。</p>
<h4 id="c-部分"><a href="#c-部分" class="headerlink" title="c++部分"></a>c++部分</h4><p>正如上篇教程,我会先奉上完整代码,然后逐步剖析。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sstream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><lua.hpp></span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>* argv[])</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="comment">// new Lua state</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Starting Lua state"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_State *lua_state = luaL_newstate();</div><div class="line"></div><div class="line"> <span class="comment">// load Lua libraries</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Loading Lua libraries"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">static</span> <span class="keyword">const</span> luaL_Reg lualibs[] = </div><div class="line"> {</div><div class="line"> {<span class="string">"base"</span>, luaopen_base},</div><div class="line"> {<span class="string">"io"</span>, luaopen_io},</div><div class="line"> {<span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line"> };</div><div class="line"> <span class="keyword">const</span> luaL_Reg *lib = lualibs;</div><div class="line"> <span class="keyword">for</span>(; lib->func != <span class="literal">NULL</span>; lib++)</div><div class="line"> {</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" loading '"</span> << lib->name << <span class="string">"'"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> luaL_requiref(lua_state, lib->name, lib->func, <span class="number">1</span>);</div><div class="line"> lua_settop(lua_state, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// start the arg table in Lua</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Creating the arg table"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> lua_createtable(lua_state, <span class="number">2</span>, <span class="number">0</span>);</div><div class="line"> lua_pushnumber(lua_state, <span class="number">1</span>);</div><div class="line"> lua_pushnumber(lua_state, <span class="number">49</span>);</div><div class="line"> lua_settable(lua_state, <span class="number">-3</span>);</div><div class="line"> lua_pushnumber(lua_state, <span class="number">2</span>);</div><div class="line"> lua_pushstring(lua_state, <span class="string">"Life is a beach"</span>);</div><div class="line"> lua_settable(lua_state, <span class="number">-3</span>);</div><div class="line"> lua_setglobal(lua_state, <span class="string">"arg"</span>);</div><div class="line"></div><div class="line"> <span class="comment">// load the script</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Loading the Lua script"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">int</span> status = luaL_loadfile(lua_state, <span class="string">"parrotscript.lua"</span>);</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" return: "</span> << status << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"></div><div class="line"> <span class="comment">// run the script with the given arguments</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Running script"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">int</span> result = <span class="number">0</span>;</div><div class="line"> <span class="keyword">if</span>(status == LUA_OK)</div><div class="line"> {</div><div class="line"> result = lua_pcall(lua_state, <span class="number">0</span>, LUA_MULTRET, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span></div><div class="line"> {</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">" Could not load the script."</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// print the values returned from the script</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Values returned from the script:"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">stringstream</span> str_buf;</div><div class="line"> <span class="keyword">while</span>(lua_gettop(lua_state))</div><div class="line"> {</div><div class="line"> str_buf.str(<span class="built_in">std</span>::<span class="built_in">string</span>());</div><div class="line"> str_buf << <span class="string">" "</span>;</div><div class="line"> <span class="keyword">switch</span>(lua_type(lua_state, lua_gettop(lua_state)))</div><div class="line"> {</div><div class="line"> <span class="keyword">case</span> LUA_TNUMBER:</div><div class="line"> str_buf << <span class="string">"script returned the number: "</span></div><div class="line"> << lua_tonumber(lua_state, lua_gettop(lua_state));</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> LUA_TTABLE:</div><div class="line"> str_buf << <span class="string">"script returned a table"</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> LUA_TSTRING:</div><div class="line"> str_buf << <span class="string">"script returned the string: "</span></div><div class="line"> << lua_tostring(lua_state, lua_gettop(lua_state));</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> LUA_TBOOLEAN:</div><div class="line"> str_buf << <span class="string">"script returned the boolean: "</span></div><div class="line"> << lua_toboolean(lua_state, lua_gettop(lua_state));</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">default</span>:</div><div class="line"> str_buf << <span class="string">"script returned an unknown-type value"</span>;</div><div class="line"> }</div><div class="line"> lua_pop(lua_state, <span class="number">1</span>);</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << str_buf.str() << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// close the Lua state</span></div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"[C++] Closing the Lua state"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>正如亲眼所见,程序的基本结构一如从前。我们打开一个状态机,加载库文件,在状态机上运行脚本,最后关闭状态机。<br>程序输出如下:</p>
<h4 id="细节剖析"><a href="#细节剖析" class="headerlink" title="细节剖析"></a>细节剖析</h4><p>细心如你者,一定发现了这次我们并未使用luaL_dofile()函数(事实上它是一个宏)来执行脚本。而是代之以luaL_loadfile()加载脚本,以lua_pcall()执行脚本。这是为了展示luaL_dofile宏的原理,实际上luaL_dofile是以上两个函数的合体,其宏定义如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">(luaL_loadfile(L, filename) || lua_pcall(L, <span class="number">0</span>, LUA_MULTRET, <span class="number">0</span>))</div></pre></td></tr></table></figure>
<p>我认为是时候,介绍一下Lua堆栈了。Lua堆栈是连接宿主语言和Lua的桥梁。宿主语言可以在堆栈中放入Lua状态机可见的数据,而Lua状态机也可以在Lua堆栈中放入宿主语言可见的数据。虽然听起来很老土,但是很有效。<br>以下代码很直观的反应了这一点:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// start the arg table in Lua</span></div><div class="line">lua_createtable(lua_state, <span class="number">2</span>, <span class="number">0</span>);</div><div class="line">lua_pushnumber(lua_state, <span class="number">1</span>);</div><div class="line">lua_pushnumber(lua_state, <span class="number">49</span>);</div><div class="line">lua_settable(lua_state, <span class="number">-3</span>);</div><div class="line">lua_pushnumber(lua_state, <span class="number">2</span>);</div><div class="line">lua_pushstring(lua_state, <span class="string">"Life is a beach"</span>);</div><div class="line">lua_settable(lua_state, <span class="number">-3</span>);</div><div class="line">lua_setglobal(lua_state, <span class="string">"arg"</span>);</div></pre></td></tr></table></figure>
<p>这段代码的作用是创建类型为table的全局变量arg作为Lua的输入参数。<br>此table使用连续存储,并含有连个元素:</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">arg</span>[<span class="number">1</span>] = <span class="number">49</span></div><div class="line"><span class="built_in">arg</span>[<span class="number">2</span>] = <span class="string">"Life is a beach"</span></div></pre></td></tr></table></figure>
<p>这段代码可以分为三部分:</p>
<h5 id="创建table"><a href="#创建table" class="headerlink" title="创建table"></a>创建table</h5><p>第一部分通过lua_createtable()函数完成,此函数创建一个匿名table并把它存入堆栈的顶部,其定义如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">lua_createtable</span><span class="params">(lua_State *L, <span class="keyword">int</span> narr, <span class="keyword">int</span> nrec)</span></span>;</div></pre></td></tr></table></figure>
<p>其中参数narr和nrec分别用于指明连续存储元素和非连续存储元素的的数量。因为我们的table只有两个连续存储的元素,所以我们传递的实参为2和0.</p>
<h5 id="填充table"><a href="#填充table" class="headerlink" title="填充table"></a>填充table</h5><p>第二部分,用期望的值填充table。首先,用lua_push*()往Lua堆栈压入两个值,第一个是table的下标,第二个是下标对应得值。然后,通过lua_settable(lua_state, -3)将上述下标和对应的值存入table,-3代表从堆栈顶部往下数第三个数据,亦即是我们创建的匿名table。<br>以上操作相当于如下代码:</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">t[k] = v</div></pre></td></tr></table></figure>
<p>v,k分别是堆栈顶部第一和第二个元素。<br>因此,以下代码:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">lua_pushnumber(lua_state, <span class="number">1</span>);</div><div class="line">lua_pushnumber(lua_state, <span class="number">49</span>);</div><div class="line">lua_settable(lua_state, <span class="number">-3</span>);</div></pre></td></tr></table></figure>
<p>就是设置我们的匿名table的下标1对应的值为49。需要注意的以上操作也将下标和对应的值弹出了堆栈,此时匿名table变成栈顶元素。</p>
<h5 id="命名table"><a href="#命名table" class="headerlink" title="命名table"></a>命名table</h5><p>第三部分,为创建和填充的table起个名字。这一步可以用lua_setglobal()函数,将table命名为全局arg的同时也将其弹出堆栈。此后,Lua就可以在脚本中识别这个table。<br>一旦脚本运行,其返回值也可以通过Lua堆栈传递给c++。需要特别注意的是,Lua将返回值按return语句后的表达式,顺序入栈,逆序出栈。<br>因为附带着冗余的系统信息,这段操作返回的信息量很大。基本上分为四步:</p>
<p>用lua_gettop()函数获取栈顶的具体位置<br>用lua_type()函数获取栈中具体位置的数据类型<br>用lua_to*()函数将堆栈中的数据转换为c++对应的类型<br>用lua_pop()函数弹出栈中的数据</p>
<p>这些函数的名字很好的解释其作用。<br>就是这样,很简单!</p>
<p>此文讨论了宿主语言和Lua共享数据的基本概念。你可以修改Lua脚本用以观察程序的输出变化。务必记住,你不需要重新编译就可以改变其执行逻辑。<br>下篇文章将讨论如何在Lua脚本中调用c++函数,敬请期待。</p>
]]></content>
<summary type="html">
<p>原文出处:<a href="http://www.acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/</a></p>
<p>我的译文如下</p>
<p>这是第二篇关于我和c++lua混编肉搏的笔记。如果你还没读过我的第一篇文章,敬请移步<a href="/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/">如何在c++程序中运行lua脚本</a>。<br>文中大多引述均来自lua用户WIKI和lua5.2的用户手册。<br>上篇文章仅仅只是抛砖引玉,c++和lua混编的强悍之处我们并未深入介绍。我希望通过以下示例让你能更进一步了解和使用lua.<br>我们的目标有两个:第一,从宿主语言c++往Lua脚本中传递参数。第二,从Lua脚本中接收返回数据。注意,Lua脚本可以返回不止一个数据哦!</p>
</summary>
<category term="lua" scheme="www.qqshark.com/categories/lua/"/>
<category term="lua" scheme="www.qqshark.com/tags/lua/"/>
<category term="c++" scheme="www.qqshark.com/tags/c/"/>
</entry>
<entry>
<title>如何在c++程序中运行lua脚本</title>
<link href="www.qqshark.com/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/"/>
<id>www.qqshark.com/2014/07/16/RUNNING-A-LUA-5-2-SCRIPT-FROM-Cpp/</id>
<published>2014-07-16T12:23:09.000Z</published>
<updated>2017-09-01T14:26:25.000Z</updated>
<content type="html"><![CDATA[<p>原文出处:<br><a href="http://www.acamara.es/blog/2012/08/running-a-lua-5-2-script-from-c/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/running-a-lua-5-2-script-from-c/</a></p>
<p>译文如下:</p>
<p>Lua 是一个胶水语言,可以很方便的去扩展其它宿主语言。说她强大是有很多原因的,而我最喜爱的莫过于她允许无需重新编译即可改变一个程序的执行逻辑。<br>不幸的是,我发现网上很少有关于lua 5.2的混编教程,而lua 5.2与c++的混编与lua 5.1,lua 5.0,还有lua 4.x是有些差别的,其中包括如下主题:</p>
<a id="more"></a>
<ol>
<li>c++如何调用Lua 脚本</li>
<li>c++与Lua之间如何互传信息</li>
<li>Lua如何调用c++</li>
<li>Lua如何动态连接c函数库</li>
<li>Lua如何实现面向对象</li>
<li>如何在c++和Lua之间互传对象</li>
</ol>
<p>此文仅是我个人关于上述第一个主题的一些看法。关于后续主题,我将稍后论述。<br>文中相关代码引用自:<br>Lua Wiki <a href="http://lua-users.org/wiki/SampleCode" target="_blank" rel="external">http://lua-users.org/wiki/SampleCode</a><br>Lua 5.2 手册 <a href="http://www.lua.org/manual/5.2/manual.html" target="_blank" rel="external">http://www.lua.org/manual/5.2/manual.html</a><br>中文手册 <a href="http://www.photoneray.com/Lua-5.2-Reference-Manual-ZH_CN/#lua_settop" target="_blank" rel="external">http://www.photoneray.com/Lua-5.2-Reference-Manual-ZH_CN/#lua_settop</a></p>
<p>我所使用的Lua为官方版本5.2.1,通过Mac osx10.8.4, gcc4.8进行编译。Lua的编译过程,以及Lua的语法细节,已超出本文范畴,具体详情请参考Lua在线文档。</p>
<h4 id="c-调用Lua脚本"><a href="#c-调用Lua脚本" class="headerlink" title="c++调用Lua脚本"></a>c++调用Lua脚本</h4><p>这是你能用c++和Lua混编做的最简单的事儿。假如你的Lua脚本的如下:</p>
<figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">-- Simple Hello World Lua program</span></div><div class="line"><span class="built_in">print</span>(<span class="string">'Hello World!'</span>)</div></pre></td></tr></table></figure>
<p>然后,你想从一个简单的c++程序里面调用它。具体步骤如下:</p>
<ol>
<li>创建Lua状态机–你可以认为是一个运行Lua脚本的虚拟机</li>
<li>加载所需要的Lua库</li>
<li>运行Lua脚本</li>
<li>关闭Lua状态机</li>
</ol>
<p>因为我们包含了Lua的头文件,故项目必须能够连接预先编译好的Lua库文件,Lua的相关头文件也必须能被项目访问。</p>
<p>完整代码如下所示:<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><lua.hpp></span></span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>* argv[])</span></span></div><div class="line"><span class="function"></span>{</div><div class="line"> <span class="comment">// create new Lua state</span></div><div class="line"> lua_State *lua_state;</div><div class="line"> lua_state = luaL_newstate();</div><div class="line"></div><div class="line"> <span class="comment">// load Lua libraries</span></div><div class="line"> <span class="keyword">static</span> <span class="keyword">const</span> luaL_Reg lualibs[] =</div><div class="line"> {</div><div class="line"> { <span class="string">"base"</span>, luaopen_base },</div><div class="line"> { <span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line"> };</div><div class="line"></div><div class="line"> <span class="keyword">const</span> luaL_Reg *lib = lualibs;</div><div class="line"> <span class="keyword">for</span>(; lib->func != <span class="literal">NULL</span>; lib++)</div><div class="line"> {</div><div class="line"> lib->func(lua_state);</div><div class="line"> lua_settop(lua_state, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// run the Lua script</span></div><div class="line"> luaL_dofile(lua_state, <span class="string">"helloworld.lua"</span>);</div><div class="line"></div><div class="line"> <span class="comment">// close the Lua state</span></div><div class="line"> lua_close(lua_state);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>程序的输出正如我们所预料的那样:</p>
<h4 id="细节分析"><a href="#细节分析" class="headerlink" title="细节分析"></a>细节分析</h4><p>让我们详细的剖析相关代码。</p>
<h5 id="第一段代码是用来创建Lua状态机。"><a href="#第一段代码是用来创建Lua状态机。" class="headerlink" title="第一段代码是用来创建Lua状态机。"></a>第一段代码是用来创建Lua状态机。</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// create new Lua state</span></div><div class="line">lua_State *lua_state;</div><div class="line">lua_state = luaL_newstate();</div></pre></td></tr></table></figure>
<p>代码的意图很明显。唯一要做的就是把通过luaL_newstate()函数创建的Lua状态机的地址保存到一个指针。然后我们就可以通过指针来使用状态机。</p>
<h5 id="第二段代码的作用是加载所需的库文件。"><a href="#第二段代码的作用是加载所需的库文件。" class="headerlink" title="第二段代码的作用是加载所需的库文件。"></a>第二段代码的作用是加载所需的库文件。</h5><p>这部分有点难以理解。每个Lua库,包括你自己生成的,都是被c++打开,并保存到Lua状态机的。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// load Lua libraries</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> luaL_Reg lualibs[] =</div><div class="line">{</div><div class="line"> { <span class="string">"base"</span>, luaopen_base },</div><div class="line"> { <span class="literal">NULL</span>, <span class="literal">NULL</span>}</div><div class="line">};</div></pre></td></tr></table></figure>
<p>然后,我们把Lua状态机的指针当做参数传给库的加载函数来加载每个库。lua_settop()函数的的调用是为了确保清除Lua堆栈的所有变量。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> luaL_Reg *lib = lualibs;</div><div class="line"><span class="keyword">for</span>(; lib->func != <span class="literal">NULL</span>; lib++)</div><div class="line">{</div><div class="line"> lib->func(lua_state);</div><div class="line"> lua_settop(lua_state, <span class="number">0</span>);</div><div class="line">}</div></pre></td></tr></table></figure>
<h5 id="第三段代码的作用是运行我们的Lua脚本。"><a href="#第三段代码的作用是运行我们的Lua脚本。" class="headerlink" title="第三段代码的作用是运行我们的Lua脚本。"></a>第三段代码的作用是运行我们的Lua脚本。</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// run the Lua script</span></div><div class="line">luaL_dofile(lua_state, <span class="string">"helloworld.lua"</span>);</div></pre></td></tr></table></figure>
<p>你唯一需要提供的就是状态机指针和脚本名称,如果脚本跟c++可执行文件不再同一目录,就加上完整路径。</p>
<h5 id="最后一段代码的作用是关闭状态机。"><a href="#最后一段代码的作用是关闭状态机。" class="headerlink" title="最后一段代码的作用是关闭状态机。"></a>最后一段代码的作用是关闭状态机。</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// close the Lua state</span></div><div class="line">lua_close(lua_state);</div></pre></td></tr></table></figure>
<p>这会清空状态机所使用的所有内存,除非一些罕见的情况。</p>
<p>以上。<br>这是最简单的c++和Lua混编。稍后会奉上更加复杂的使用案例,敬请期待。</p>
]]></content>
<summary type="html">
<p>原文出处:<br><a href="http://www.acamara.es/blog/2012/08/running-a-lua-5-2-script-from-c/" target="_blank" rel="external">http://www.acamara.es/blog/2012/08/running-a-lua-5-2-script-from-c/</a></p>
<p>译文如下:</p>
<p>Lua 是一个胶水语言,可以很方便的去扩展其它宿主语言。说她强大是有很多原因的,而我最喜爱的莫过于她允许无需重新编译即可改变一个程序的执行逻辑。<br>不幸的是,我发现网上很少有关于lua 5.2的混编教程,而lua 5.2与c++的混编与lua 5.1,lua 5.0,还有lua 4.x是有些差别的,其中包括如下主题:</p>
</summary>
<category term="lua" scheme="www.qqshark.com/categories/lua/"/>
<category term="lua" scheme="www.qqshark.com/tags/lua/"/>
<category term="c++" scheme="www.qqshark.com/tags/c/"/>
</entry>
</feed>