C++ 名前マングリング(Name mangling)(備忘録)

「名前マングリング(Name mangling)」について、実機で挙動確認をした時のメモです。



名前マングリング(Name mangling)


■C++の場合、シンボル名に「名前マングリング(Name mangling)」と呼ばれる処理が施される為に、
共有ライブラリーを利用する時には、関数名の指定はその「名前マングリング」された名前を指定しなければならない。

もしくは、共有ライブラリー側で「名前マングリング」を抑止(デマングル)し、関数名のママとする必要がある。

■C言語の場合は、名前マングリングは行われない。



先にまとめ


■名前マングリングの結果
0000067c T _Z9SOtest005c ← SOtest005はこのようになる
00000680 T _Z9SOtest006i ← SOtest006はこのようになる

目的はオーバーロードの実現の為と思われる。



■デマングル
ヘッダファイルをCとC++で共有するために
#ifdef __cplusplus
extern "C" {
#endif
ここにexternの定義をする。複数可能。
#ifdef __cplusplus
}
#endif

結果は
00000668 T SOtest002
00000670 T SOtest003
00000678 T SOtest004
のように「名前マングリング」されない。



■CPP側のextern指定
ヘッダファイル側とCPPファイル側の両方でextern指定をすると、「名前マングリング」の抑止(デマングル)指定をしても、
「名前マングリング」された事があった。ただし、再現できなかった。記憶の片隅に置いておく事にします。



■extern指定なしのシンボル名(今回は関数名)
FreePascal側で宣言している

function SOtest006(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name '_Z9SOtest006i';

はCPP,h側では extern は指定していない。
しかし、利用出来る。
ただし、シンポル名は「名前マングリング」された名前となる。



■FreePascal側でのオーバーロード

(1)宣言
function SOtest002(a : integer; b : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest002';
function SOtest002(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';

(2)呼び出し
c := SOtest002(3,6);
memo1.lines.add('SOtest002(3,6) : ' + inttostr(c));

c := SOtest002(2);
memo1.lines.add('SOtest002(2) : ' + inttostr(c));

(3)結果
SOtest002(3,6) : -3
SOtest002(2) : 702

この事から「デマングル」はしない方がよいかもしれない。



環境


■Eclipse IDE for C/C++ Developers
Version: Neon.3 Release (4.6.3)
Build id: 20170314-1500
(Windows 10 64bitで実行)

■ハード:Raspberry Pi 3 Model B V1.2

■pi@rp3a:~ $ uname -a
Linux rp3a 4.9.24-v7+ #993 SMP Wed Apr 26 18:01:23 BST 2017 armv7l GNU/Linux

■Lazarus
バージョン #:1.2.4+dfsg2-1
FPCバージョン 2.6.4
(Raspberry Pi 3で実行)




テスト


■ソース
(1)共有ライブラリー
xxx.cpp
#include "RaspbianSOtest001.h"

int SOtest002(int a,int b) {return a - b;}
int SOtest003(void) {return 3;}
extern void SOtest004(void){}
void SOtest005(char a){}
int SOtest006(int a){return a + 600;}
int SOtest007(int a){return a + 700;}



ヘッダファイル
RaspbianSOtest001.h

#ifdef __cplusplus
extern  "C"  {
#endif
extern int SOtest002(int a,int b);
extern int SOtest003(void);
extern void SOtest004(void);
//extern int SOtest007(int a);
#ifdef __cplusplus
}
#endif

extern void SOtest005(char a);
extern "C" {int SOtest007(int a);}




(2)共有ライブラリーを使用するFreePascal
unit u_app;

{$mode objfpc}{$H+}

interface

uses
  dl,
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

function SOtest002(a : integer; b : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest002';
function SOtest006(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name '_Z9SOtest006i';
function SOtest007(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';
function SOtest002(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';


type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  lib : pointer;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  c : integer;
begin
  c := 123;
  //c := SOtest002(10,5);
  //SOtest004;

  c := SOtest002(3,6);
  memo1.lines.add('SOtest002(3,6) : ' + inttostr(c));

  c := SOtest006(6);
  memo1.lines.add('SOtest006(6) : ' + inttostr(c));

  c := SOtest007(70);
  memo1.lines.add('SOtest007(70) : ' + inttostr(c));

  c := SOtest002(2);
  memo1.lines.add('SOtest002(2) : ' + inttostr(c));

end;
begin
end.




■実行結果
Memo1
SOtest002(3,6) : -3
SOtest006(6) : 606
SOtest007(70) : 770
SOtest002(2) : 702




■シンボル名確認 nm libRaspbianSOtest001.so 実行結果
root@rp3a:/usr/lib# nm libRaspbianSOtest001.so
00000668 T SOtest002
00000670 T SOtest003
00000678 T SOtest004
00000688 T SOtest007


0000067c T _Z9SOtest005c
00000680 T _Z9SOtest006i




スポンサーサイト

C++ volatile forループ変数の効果を目で見る(備忘録)

最適化を抑止する volatile を空ループのループ変数に使用した場合の効果を目で見えるようにして確認しました。

下記のforの比較です。

for (volatile int n = 0;5000 > n;n++){};

for (int n = 0;5000 > n;n++){};



テストの概要


1.Raspberry Pi のGPIO端子に信号を出し、それをオシロスコープで観測する。
2.forループの直前でGPIO27をONにし、
3.forループを実行
4.forループの直後にGPIO27をOFFとする。
5.テストの最初には、オシロスコープでトリガを掛けやすいように基本パルスを発生させる。
6.それぞれの間にsleepで時間をとる。

ソース概要


int main(int argc, char *argv[], char *envp[])
{

//メモリマップ取得
    sel = get_gpio_map();
    if ((int)sel == -1) {
        return 1;
    }

    //GPIO27をOUTPUTに設定
    GPFSELOUTPUT(sel,27);  //sel->fsel27 = GPIOOUTPUT;

    for (int i = 0;1000000>i;i++){
        //基本パルス幅確認用
        GPSETN(sel,27); //ポートをON
        nano_sleep(100000);
        GPCLRN(sel,27); //ポートをOFF
        nano_sleep(100000);

        //for 内
        GPSETN(sel,27); //ポートをON
        for (volatile int n = 0;5000 > n;n++){};
        GPCLRN(sel,27); //ポートをOFF

        nano_sleep(100000);

        //for 内
        GPSETN(sel,27); //ポートをON
        for (int n = 0;5000 > n;n++){};
        GPCLRN(sel,27); //ポートをOFF

        nano_sleep(1000000);
    }


    return 0;
}


※ GPSETN() GPCLRN() はGPIOポートのON,OFF制御用です。

結果


C++ volatile forループ変数の効果を目で見る(備忘録)
最初のパルはトリガ用のパルス。
中央のパルスがvolatileを指定したforループの実行期間。
三番目の細いパルスはvolatileなしのループの実行期間。

volatileを指定しない空ループはネグられている事がわかります。


※実行環境については省力します。

C++でファイルのパーミッションを変更する chmod() (備忘録)

■ソース
#include <stdio.h>
#include <sys/stat.h>

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(){
    string filename = "/sys/class/gpio/gpio27/direction";
    if (chmod(filename.c_str(),0x1ff) == 0) {
        cout << "chmod OK (" + filename + ")" << endl;
    } else {
        cout << "chmod error (" + filename + ")" << endl;
    }

    filename = "/sys/class/gpio/gpio27/value";
    if (chmod(filename.c_str(),0x77)== 0) {
        cout << "chmod OK (" + filename + ")" << endl;
    } else {
        cout << "chmod error (" + filename + ")" << endl;
    }
}

■実行結果
sudo ./test01

※実行前
-rw-r--r-- 1 root root 4096 12月  4 11:51 /sys/class/gpio/gpio27/active_low
lrwxrwxrwx 1 root root    0 12月  4 11:51 /sys/class/gpio/gpio27/device -> ../../../20200000.gpio
-rw-r--r-- 1 root root 4096 12月  4 11:51 /sys/class/gpio/gpio27/direction
-rw-r--r-- 1 root root 4096 12月  4 11:51 /sys/class/gpio/gpio27/edge
lrwxrwxrwx 1 root root    0 12月  4 11:50 /sys/class/gpio/gpio27/subsystem -> ../../../../../../class/gpio
-rw-r--r-- 1 root root 4096 12月  4 11:50 /sys/class/gpio/gpio27/uevent
-rw-r--r-- 1 root root 4096 12月  4 11:51 /sys/class/gpio/gpio27/value

※実行後
-rw-r--r-- 1 root root 4096 12月  4 11:54 /sys/class/gpio/gpio27/active_low
lrwxrwxrwx 1 root root    0 12月  4 11:54 /sys/class/gpio/gpio27/device -> ../../../20200000.gpio
-rwxrwxrwx 1 root root 4096 12月  4 11:54 /sys/class/gpio/gpio27/direction
-rw-r--r-- 1 root root 4096 12月  4 11:54 /sys/class/gpio/gpio27/edge
lrwxrwxrwx 1 root root    0 12月  4 11:54 /sys/class/gpio/gpio27/subsystem -> ../../../../../../class/gpio
-rw-r--r-- 1 root root 4096 12月  4 11:54 /sys/class/gpio/gpio27/uevent
---xrw-rwx 1 root root 4096 12月  4 11:54 /sys/class/gpio/gpio27/value

■key
Raspberry Pi GPIO アクセス権

※2015/11実行
お知らせ
■注意:Google Chrome以外のブラウザでは動作しない事もあります。
お好みに応じて
画像だけの表示でいいよ
やっぱり全部表示して
背景は黒がいいな
背景を元に戻して
サブジャンル
メモリアルマップ
My Favorite Photo
検索フォーム
プロフィール

otsu.usiwakamaru

Author:otsu.usiwakamaru
五条の橋でひらりひらりと欄干を飛び渡る牛若丸のように、興の向くまま電子回路にプログラミングに写真にと飛び回っています。

プロフィール詳細

カレンダー
09 | 2017/10 | 11
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 - - - -
キーワード
クリックしたキーワードの記事のみ表示します。

電池 試み IXY デザイン  改造 3D ミッキー 

最新記事
月別アーカイブ
全記事表示リンク

全ての記事を表示する

おすすめプログ(新着記事)
リンク


にほんブログ村
カテゴリ
ART (1)
橋 (0)
PIC (2)
カウンタ
訪問者数(UU)

アクセス数

現在の閲覧者数

tael no013用