合計 昨日 今日

naohiro19
 
記事: 247
登録日時: 2010年10月16日(土) 20:16
お住まい: 愛知県
日記: 日記を見る (116)
日記
- 1月 2018
+ 12月 2017
+ 11月 2017
+ 10月 2017
+ 8月 2017
+ 7月 2017
+ 6月 2017
+ 5月 2017
+ 1月 2017
+ 9月 2016
+ 8月 2016
+ 7月 2016
+ 6月 2016
+ 5月 2016
+ 4月 2016
+ 9月 2015
+ 8月 2015
+ 7月 2015
+ 6月 2015
+ 11月 2014
+ 10月 2014
+ 8月 2014
+ 7月 2014
+ 6月 2014
+ 5月 2014
+ 4月 2014
+ 3月 2014
+ 12月 2013
+ 10月 2013
+ 9月 2013
+ 7月 2013
+ 6月 2013
+ 5月 2013
+ 10月 2012
+ 8月 2012
+ 7月 2012
+ 6月 2012
+ 5月 2012
+ 11月 2011
カテゴリー
講座
7 記事
勉強
4 記事
プログラミング
30 記事
フィード
次へ

Boostの多倍長整数ライブラリ(multiprecision)を使えば1万桁を超える計算ができる

パーマリンクby naohiro19 on 2018年1月18日(木) 16:56 カテゴリー: プログラミング

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
 
using namespace std;
using namespace boost::multiprecision;
 
 
cpp_int fact(const cpp_int& n) {
    if (n == 0) return 1;
    return n * fact(n - 1);
}
 
int main()
{
    cout << fact(100) << endl;
}

100の階乗を計算すると以下のようになります。それにしてもすごい桁数ですね。
コード[C++]: 全て選択
1
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

コメント数: 0 閲覧数: 61

C++ のタプルを利用すると関数の戻り値を複数個受け取ることができます

パーマリンクby naohiro19 on 2018年1月08日(月) 12:30 カテゴリー: 勉強, プログラミング

C++11では <tuple> というヘッダーファイルが使えます。タプルはpairが拡張されたものです。
関数の戻り値として std::tuple にして 関数の return 文では make_tuple を利用します。

サンプルプログラムを以下に載せておきます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
 
tuple<int, int, int, int> add_sub_mul_div(int x, int y) {
    return make_tuple(
        x + y,
        x - y,
        x * y,
        x / y
    );
}
 
int main()
{
    int addres, subres, mulres, divres;
    tie(addres, subres, mulres, divres) = add_sub_mul_div(10, 20);
 
    cout << "足し算:" << addres << endl;
    cout << "引き算:" << subres << endl;
    cout << "掛け算:" << mulres << endl;
    cout << "割り算:" << divres << endl;
}


実行結果
コード[C++]: 全て選択
1
2
3
4
足し算:30
引き算:-10
掛け算:200
割り算:0

コメント数: 0 閲覧数: 184

[LuaとC++の連携] Lua C APIを使って C/C++とLuaを連携させる方法

パーマリンクby naohiro19 on 2017年12月23日(土) 20:22 カテゴリー: プログラミング

blog.php?u=79&b=6869 この記事を書きましたが、純粋な Lua C APIを使って以下のようにグローバル変数の設定・取得、C言語関数の呼び出しをやってみたいと思います。
Lua C APIは第1引数に lua_State のポインターを渡す必要があります。Luaはエラーがなければ LUA_OK(=0)を返します。



Luaからグローバル変数の値を取得
コード[Lua]: 全て選択
1
w = 100

こういう Luaのグローバル変数がある場合は
  1. lua_getglobal関数でLuaの変数名を指定
  2. lua_toXXXの関数で実際に値を取り出す。
  3. スタックが残ったままになっているので lua_popでスタックを空っぽにする


実際のコード例は以下のようになります。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <lua.hpp>
#include "PrintStack.h"
 
int main()
{
   
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
   
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
   
    lua_getglobal(L, "w");
    int w = lua_tointeger(L, -1);
    lua_pop(L, 1);
    printf("w = %d\n", w);
    lua_close(L);
}




こんどは C/C++から Luaにグローバル変数を登録してそれを Luaで表示させるとうことをやってみましょう。
グローバル変数の取得は lua_getglobal→lua_tonumberという順番ですが、設定する場合は値をlua_pushXXXで値をプッシュしてからlua_setglobalを呼び出します。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <lua.hpp>
#include "PrintStack.h"
 
int main()
{
   
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
 
    constexpr int MAX_SHOP_ITEMS = 5;
    lua_pushnumber(L, MAX_SHOP_ITEMS);
    lua_setglobal(L, "MAX_SHOP_ITEMS");
   
   
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
   
    lua_close(L);
}


上記のMAX_SHOP_ITEMSをLuaから使うには以下のように書けば利用ができます。
コード[Lua]: 全て選択
1
print(MAX_SHOP_ITEMS) -- 5



続いて C/C++から Luaの関数を呼ぶ例です。
コード[Lua]: 全て選択
1
2
3
function add(x, y)
    return x + y
end

Luaで定義したadd関数を呼び出すには
  1. lua_getglobal関数を使って add関数をスタックに積む
  2. lua_pushXXXで引数に渡す
  3. lua_pcallを使ってLuaの関数を呼び出す
  4. lua_toXXXXで引数を取得す
という手順になります。

以下がC/C++のプログラムです。
コード[C++]: 全て選択
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
#include <iostream>
#include <lua.hpp>
#include "PrintStack.h"
 
int main()
{
   
    // Luaの初期化
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
   
    // ファイルを読み込む
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
 
    // add 関数を積む
    lua_getglobal(L, "add");
 
    // 引数は2個
    lua_pushinteger(L, 10);
    lua_pushinteger(L, 20);
 
    // Luaの関数を呼ぶ(引数:2個、戻り値:1個)
    if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
   
    // 結果を表示
    printf("%d\n", lua_tointeger(L, -1));
   
 
    lua_close(L);
   
}




Luaから二つの引数を取りC言語の関数を呼び出して4つ返す関数です。以下のポイントがあります。
  1. LuaからC言語の関数を実行するには int型を戻り値として、引数としてlua_State構造体のポインターにする
  2. Luaのスタックから lua_toXXX関数を使って引数を取得
  3. 引数をスタックを lua_settop(L, 0); として空っぽにする
  4. 目的の関数を実行
  5. 結果を Luaのスタックにプッシュする
  6. return 文は戻り値の数を指定する
コード[C++]: 全て選択
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
#include <iostream>
#include <lua.hpp>
 
int add_c(int x, int y) {
    return x + y;
}
 
int sub_c(int x, int y) {
    return x - y;
}
 
int mul_c(int x, int y) {
    return x * y;
}
 
int div_c(int x, int y) {
    return x / y;
}
 
int multiply(lua_State* L) {
    int x = lua_tointeger(L, 1);
    int y = lua_tointeger(L, 2);
    lua_settop(L, 0);
 
    int add_ret = add_c(x, y);
    int sub_ret = sub_c(x, y);
    int mul_ret = mul_c(x, y);
    int div_ret = div_c(x, y);
 
    lua_pushinteger(L, add_ret);
    lua_pushinteger(L, sub_ret);
    lua_pushinteger(L, mul_ret);
    lua_pushinteger(L, div_ret);
    return 4;
}
 
 
int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
 
    lua_register(L, "multiply", multiply);
 
    if (luaL_dofile(L, "sample.lua") != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return 0;
    }
 
    lua_close(L);  
}

上記のadd_c/sub_c/mul_c/div_c関数をLuaから呼び出すには以下のように書きます。
コード[Lua]: 全て選択
1
2
3
4
5
6
7
 
a, b, c, d = multiply(10, 9)
 
print(a)
print(b)
print(c)
print(d)
最後に編集したユーザー naohiro19 [ 2017年12月24日(日) 00:34 ], 累計 2 回

コメント数: 0 閲覧数: 237

[LuaとC++の連携] Sol2を使って LuaとC++を連携させるテスト

パーマリンクby naohiro19 on 2017年12月18日(月) 20:53 カテゴリー: プログラミング

https://github.com/ThePhD/sol2 読み方は「ソル」で、ポルトガル語で「太陽」という意味を表します。

このライブラリを使うと C++ と Luaをうまく連携できます。 C++11/C++14に対応しているのでVisual Studio 2015/2017、Clang、GCCで動作します。

コード[Lua]: 全て選択
1
2
3
function lua_add(a, b)
   return (a+b)
end

この lua_add関数を C++から呼び出すには 以下のように書きます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define SOL_CHECK_ARGUMENTS 1
#include <lua.hpp>
#include "sol.hpp"
#include <iostream>
 
using namespace std;
 
int main(int, char*[]) {
   
    // Luaの初期化
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::package);
   
    // Luaスクリプトファイルの読み込み
    lua.script_file("sample.lua");
 
    // Luaの関数を呼び出す
    double ret = lua["lua_add"](12, 16);
 
    // 結果の表示
    cout << "ret = " << ret << endl;
 
    return 0;
}


逆に C++の関数を呼び出す場合も簡単です。また C++11のラムダ式の関数オブジェクトもLua側で呼び出せます。
コード[C++]: 全て選択
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
#define SOL_CHECK_ARGUMENTS 1
#include <lua.hpp>
#include "sol.hpp"
#include <iostream>
 
using namespace std;
 
int c_add(int x, int y) {
    return x + y;
}
 
int main(int, char*[]) {
   
    // Luaの初期化
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::package);
 
    lua["add"] = &c_add;
    lua["add2"] = [](int x, int y) { return x + y; };
   
    // Luaスクリプトファイルの読み込み
    lua.script_file("sample.lua");
 
    return 0;
}

この場合 c_addをaddとしてLua側に登録し、ラムダ式の関数オブジェクトとしてLuaに登録しています。
Luaからこの二つの関数を呼び出すには以下のように書けばOKです。
コード[Lua]: 全て選択
1
2
print(add(10, 20))
print(add2(10, 20))


Luaの変数の値を取得するにも簡単です
例えば以下のような Luaにmessage という変数に「Hello, world!」という文字列がある場合もメンバー関数のgetを使います。
コード[Lua]: 全て選択
1
message = "Hello, world!"

この値をC++で取得するソースコードは以下のようになります。
コード[C++]: 全て選択
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
#define SOL_CHECK_ARGUMENTS 1
#include <lua.hpp>
#include "sol.hpp"
#include <iostream>
 
using namespace std;
 
int c_add(int x, int y) {
    return x + y;
}
 
 
int main(int, char*[]) {
   
    // Luaの初期化
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::package);
   
    // Luaスクリプトファイルの読み込み
    lua.script_file("sample.lua");
 
    auto message = lua["message"].get<std::string>();
   
    cout << message << endl;
 
    return 0;
}


C++11の constexprも定数としてLuaに公開できます。
コード[C++]: 全て選択
1
2
constexpr int MAXLENGTH = 10;
lua["MAXLENGTH"] = MAXLENGTH;

上記の定数を Luaで使う場合も以下のように書くことができます。
コード[Lua]: 全て選択
1
print(MAXLENGTH)


以下のようなテーブルを返す Luaの関数 initがあります。
コード[Lua]: 全て選択
1
2
3
4
5
6
function init()
    return {
        width = 640,
        height = 480
    };
end


このinit関数の戻値であるテーブルから widthとheightを取り出す場合は以下のように書けば取り出せます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
 sol::table ret = lua["init"]();
   
double width = ret["width"].get<double>();
double height = ret["height"].get<double>();
 
std::cout << "width = " << width << std::endl;
std::cout << "height = " << height << std::endl;


ポイントは以下のようにします。
  1. sol::tableを戻り値として受け取る
  2. sol::tableの[]演算子でテーブル名を指定して get<型名>(); でテーブルに入っている値を取り出す
最後に編集したユーザー naohiro19 [ 2017年12月21日(木) 21:33 ], 累計 3 回

コメント数: 0 閲覧数: 463

フォーラムルール違反を見つけました

パーマリンクby naohiro19 on 2017年12月13日(水) 23:17


フォーラムルールより
また、「初心者です」「初心者」「初めまして」「名無し」のような
その場だけの名前、また、多くの人が重複して使うであろう名前は避けてください。
なるべくオリジナルな名前を決め、以後同じ名前を使い続けてください

とあるようにフォーラムルール違反となっています。

アクセスログはわかりませんが接続元のIPアドレスが同一なはずです。

コメント数: 0 閲覧数: 270

オンラインデータ

登録ユーザー: みけCAT