<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
	<title><![CDATA[ タグ「include」を含む投稿［3件］ - 電装工芸日記 - 舞台照明機器の製作とか - ]]></title>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi</link>
	<description><![CDATA[ 今年は開発案件を進めたい ]]></description>
	<language>ja</language>
	<copyright>Copyright 2026</copyright>
	<lastBuildDate>Tue, 07 Apr 2026 17:07:41 +0900</lastBuildDate>
	<generator><![CDATA[ <!-- てがろぐ Version: -->Powered by <a href="https://www.nishishi.com/cgi/tegalog/" target="_top">てがろぐ</a> Ver 3.4.0 ]]></generator>
	<!-- BEGIN ENTRIES -->
	<!-- One Entry Data for RSS Feed -->
<item>
	<title><![CDATA[ 　しばらく前に書いた Art-Net を扱うコードです。 ]]></title>
	<description><![CDATA[ 　しばらく前に書いた Art-Net を扱うコードです。<br />　今だったらこうするのにってところは多いですが、これをたたき台にしようかなと。<br />　表示の都合で一部の文字を全角にしています。コピペしてお使いになる際はご注意ください。オレオレライブラリーやオレオレヘッダーが必要なのでこのソースだけでは動きませんけど、要点の参考になれば幸いかと。<br /><br /><small class="decorationS"><span class="decorationF deco-code">/*　--------------<br />　　Art-Net Engine<br />　　ae_main.c<br />　　-------------- */<br /><br />// 汎用ライブラリをインクルード<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;stdio.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;string.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;unistd.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;time.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;sys/types.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;sys/socket.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;arpa/inet.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;sys/ioctl.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;sys/shm.h&gt;<br />//#include &lt;netinet/in.h&gt;<br />//#include &lt;sys/ipc.h&gt;<br /><br />// 自作ライブラリをインクルード<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &quot;ae_main.h&quot;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &quot;std_inkey.h&quot;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &quot;std_dump.h&quot;<br /><br />// Main<br />int main( int argc, char *argv〔〕 ) {<br />　　// 汎用変数<br />　　// int i ;<br />　　// int ret = 0 ;<br />　　// 共有メモリ変数<br />　　ae_sharemem_t *ae_sharemem ;<br />　　int ae_sharememsize = sizeof( ae_sharemem_t ) ;<br />　　int ae_sharememID ;<br />　　//【開発用】共有メモリ領域の確保 上位モジュールが出来たらそちらで作る<br />　　ae_sharememID = shmget( IPC_PRIVATE, ae_sharememsize, SHM_R|SHM_W ) ;<br />　　// 共有メモリ定義<br />　　ae_sharemem = shmat( ae_sharememID, 0, SHM_R|SHM_W ) ;<br />　　// nsec時変数<br />　　struct timespec now ;　　　　　　　　　　　 // 現在POSIX時を得る構造体<br />　　unsigned long long int start_nsec ;　　　　 // 処理開始nsec時を保存<br />　　//【開発用】処理時間変数<br />　　unsigned long long int lap_nsec ;　　　　　 // 処理終了nsec時<br />　　static unsigned long long int max_nsec = 0 ; // 経過したnsecの最大値<br />　　// Art-Net 受信変数<br />　　int an_rx ;　　　　　　　　　　　　　　　　 // 受信socket番号<br />　　struct sockaddr_in an_rx_addr ;　　　　　　 // 受信先指定構造体<br />　　int an_rx_length ;　　　　　　　　　　　　　// recvfromで得たデータ長<br />　　char an_rx_nic〔〕 = { &quot;eth0&quot; } ;　　　　　　 // 受信NICの名称<br />　　char an_rx_buf〔 ADMX_BUF_SIZE 〕 ;　　　　　 // 受信バッファ ArtDMXの最大バイト長で設定<br />　　socklen_t an_rx_sin_size = ADMX_BUF_SIZE ;　// recvfromに渡す受信バッファサイズ<br />　　struct sockaddr_in an_rx_from_addr ;　　　　// 送信元情報の構造体<br />　　artdmx_t artdmx_rx ;　　　　　　　　　　　　// 受信したArtDMXを保存する構造体<br />　　// Art-Net 送信変数<br />　　int an_tx ;　　　　　　　　　　　　　　　　 // 送信socket番号<br />　　struct sockaddr_in an_tx_addr ;　　　　　　 // 送信先指定構造体<br />　　char an_tx_nic〔〕 = { &quot;eth1&quot; } ;　　　　　　 // 受信NICの名称<br />　　int yes = 1 ;　　　　　　　　　　　　　　　 // 送信をブロードキャストに設定する際のフラグ変数<br />　　artdmx_t artdmx_tx〔 ADMX_TX_UNIVRESES 〕 ;　 // 送信するArtDMXを保存する構造体配列<br />　　char an_tx_buf〔 ADMX_BUF_SIZE 〕 ;　　　　　 // 送信バッファ Art-DMXの最大バイト長で設定<br />　　int an_tx_count = 0 ;　　　　　　　　　　　 // 送信ユニバースカウンタ<br />　　unsigned long long int an_tx_nsec = 0 ;　　 // 送信nsec時を保存<br />　　float an_tx_fps = 29.97 ;　　　　　　　　　 // 送信フレームレート<br />　　unsigned int an_tx_interval =<br />　　　　　　( unsigned int )( 1e9 / ADMX_TX_UNIVRESES / an_tx_fps ) ;<br /><br />　　// Art-Netの受信ソケットを作成<br />　　an_rx = socket( AF_INET, SOCK_DGRAM, 0 ) ;　　　　　　　　　　　　　// 受信ソケットのインスタンスを作成<br />　　setsockopt( an_rx, SOL_SOCKET, SO_BINDTODEVICE,　　　　　　　　　　 // 受信NICを指定する <br />　　　　　　　　&an_rx_nic, sizeof( an_rx_nic ) ); <br />　　an_rx_addr.sin_family = AF_INET ;　　　　　　　　　　　　　　　　　 // 受信をUDPに設定<br />　　an_rx_addr.sin_port = htons( AN_PORT ) ;　　　　　　　　　　　　　　// 受信ポート番号を設定<br />　　an_rx_addr.sin_addr.s_addr = INADDR_ANY ;　　　　　　　　　　　　　 // 送信元アドレスを無指定にする<br />　　bind( an_rx, ( struct sockaddr * ) &an_rx_addr,　　　　　　　　　　 // 上記をインスタンスに設定する<br />　　　　　　　　　　sizeof( an_rx_addr ) ) ;<br />　　// Art-Netの送信ソケットを作成<br />　　an_tx = socket( AF_INET, SOCK_DGRAM, 0 ) ;　　　　　　　　　　　　　// 送信ソケットのインスタンスを作成<br />　　an_tx_addr.sin_family = AF_INET ;　　　　　　　　　　　　　　　　　 // 送信をUDPに設定<br />　　an_tx_addr.sin_port = htons( AN_PORT ) ;　　　　　　　　　　　　　　// 送信ポート番号を設定<br />　　an_tx_addr.sin_addr.s_addr = inet_addr( &quot;255.255.255.255&quot; ) ;　　　 // 送信先アドレスを無指定にする<br />　　setsockopt( an_tx, SOL_SOCKET, SO_BINDTODEVICE,　　　　　　　　　　 // 送信NICを指定する <br />　　　　　　　　&an_tx_nic, sizeof( an_tx_nic ) ) ; <br />　　setsockopt( an_tx, SOL_SOCKET, SO_BROADCAST,　　　　　　　　　　　　// 送信をブロードキャストに設定<br />　　　　　　　　( char * )&yes, sizeof( yes ) ) ;<br />　　// std_inkey 用変数<br />　　int key_code_length = 0 ;<br />　　int key_code_length_st = 0 ;<br />　　char key_code〔 32 〕 = { 0x00 } ;<br />　　char key_code_st〔 32 〕 = { 0x00 } ;<br />　　// std_inkey を開始<br />　　set_inkey( SET ) ;<br /><br />　　// ***** Art-Netの受送信と表示 *****<br />　　printf( &quot;\e〔2J\e〔?25l&quot; ) ;　　　　　　　　 // 画面を消去 カーソル非表示　\e〔?25l カーソル非表示<br />　　while( strcmp( key_code, _KEY_F12 ) != 0 ) {<br />　　　　// ------ 開始nsec時を取得 ------<br />　　　　clock_gettime( CLOCK_REALTIME, &now ) ;　　　　　　　　　　 // 現在POSIX時間値取得<br />　　　　start_nsec = ( unsigned long long int )now.tv_sec * 1e9　　 // unsigned long long int型(8バイト長int)変数に<br />　　　　　　　　　　 + now.tv_nsec ;　　　　　　　　　　　　　　　　// 取得値をひとまとめにする(nsec)<br /><br />　　　　// --------- キー入力 ----------<br />　　　　key_code_length = get_inkey( key_code ) ;　　　　　　　　　 // キー入力を取得<br />　　　　if( strcmp( key_code, &quot;\x20&quot; ) == 0 ) max_nsec = 0 ;　　　　//【開発用】キー入力が〔SP〕なら実行時間計測の最大値をクリア<br />　　　　if( key_code_length &gt; 0 ) {　　　　　　　　　　　　　　　　 // キー入力を別関数に渡すためのスタック<br />　　　　　　key_code_length_st = key_code_length ;<br />　　　　　　memcpy( key_code_st, key_code, sizeof( key_code ) ) ;<br />　　　　}<br /><br />　　　　// --------- 受 信 -----------<br />　　　　memset( an_rx_buf, 0, ADMX_BUF_SIZE ) ;　　　　　　　　　　　　　　　　　　　　 // 受信バッファのクリア<br />　　　　an_rx_length = recvfrom( an_rx, an_rx_buf, ADMX_BUF_SIZE, MSG_DONTWAIT,　　　　 // an_rx_from_addrには送信元情報が入る<br />　　　　　　　　( struct sockaddr * )&an_rx_from_addr, &an_rx_sin_size ) ;<br />　　　　// 受信がある場合<br />　　　　if( an_rx_length &gt; 0 ) {　　　　　　　　　　　　　　　　　　　　　　　　　　　　// an_rx_lengthは受信値のバイト長<br />　　　　　　// 送信元IPアドレスとポートを抽出し、構造体artdmx_rxに保存<br />　　　　　　inet_ntop( AF_INET, &an_rx_from_addr.sin_addr,　　　　　　　　　　　　　　　// 受信データから送信元IPアドレスを抽出保存<br />　　　　　　　　　　　　artdmx_rx.senderip, sizeof( artdmx_rx.senderip ) ) ;<br />　　　　　　strcpy( artdmx_rx.senderip, inet_ntoa( an_rx_from_addr.sin_addr ) ) ;<br />　　　　　　artdmx_rx.senderport = ntohs( an_rx_from_addr.sin_port ) ;　　　　　　　　　// 受信データから送信元ポートを抽出保存<br />　　　　　　artdmx_rx.recv_nsec = start_nsec ;　　　　　　　　　　　　　　　　　　　　　// 受信日時を保存<br />　　　　　　// 受信したArtDMXをデコード<br />　　　　　　if( artdmx_decode( an_rx_buf, &artdmx_rx ) &gt;= 0 )　　　　　　　　　　　　　 // ArtDMXなら送信スタックに保存<br />　　　　　　　　memcpy( &artdmx_tx〔 artdmx_rx.universe 〕,　　　　　　　　　　　　　　　 // ArtDMX以外なら読み飛ばし<br />　　　　　　　　　　　　&artdmx_rx, sizeof( artdmx_t ) ) ;<br /><br />　　　　　　//【開発用】終了nsec時を取得<br />　　　　　　clock_gettime( CLOCK_REALTIME, &now ) ;　　　　　　　　　　　　　　 // 現在POSIX時間値取得<br />　　　　　　lap_nsec = ( unsigned long long int )now.tv_sec * 1e9　　　　　　　 // unsigned long long int型(8バイト長int)変数に<br />　　　　　　　　　　　　+ now.tv_nsec - start_nsec ;　　　　　　　　　　　　　　// 取得値をひとまとめにする(nsec)<br />　　　　　　if( max_nsec &lt; lap_nsec ) max_nsec = lap_nsec ;　　　　　　　　　　 // ここまでの最大処理時間を得る<br /><br />　　　　}<br /><br />　　　　// --------- 送 信 -----------<br />　　　　else if( start_nsec - an_tx_nsec &gt; ( unsigned int )( an_tx_interval ) ) {<br />　　　　　　artdmx_encode( an_tx_buf, &artdmx_tx〔 an_tx_count 〕 ) ;　　　　　　 // 送信データをエンコード<br />　　　　　　sendto( an_tx, an_tx_buf, ADMX_BUF_SIZE, MSG_DONTWAIT,　　　　　　　// 送信実行<br />　　　　　　　　　　( struct sockaddr * )&an_tx_addr, sizeof( an_tx_addr ) ) ;<br />/*<br />　　　　　　//【開発用】終了nsec時を取得<br />　　　　　　clock_gettime( CLOCK_REALTIME, &now ) ;　　　　　　　　　　　　　　 // 現在POSIX時間値取得<br />　　　　　　lap_nsec = ( unsigned long long int )now.tv_sec * 1e9　　　　　　　 // unsigned long long int型(8バイト長int)変数に<br />　　　　　　　　　　　　+ now.tv_nsec - start_nsec ;　　　　　　　　　　　　　　// 取得値をひとまとめにする(nsec)<br />　　　　　　if( max_nsec &lt; lap_nsec ) max_nsec = lap_nsec ;　　　　　　　　　　 // ここまでの最大処理時間を得る<br />*/<br />　　　　　　//【開発用】受信データの表示<br />　　　　　　artdmx_check_disp( &artdmx_tx〔 an_tx_count 〕,　　　　　　　　　　　 // 送信データの仮表示 <br />　　　　　　　　　　key_code_st, &key_code_length_st, &lap_nsec, &max_nsec ) ;<br />　　　　　　// 送信事後処理<br />　　　　　　an_tx_nsec = start_nsec ;　　　　　　　　　　　　　　　　　　　　　 // 送信インターバル・次回用のnsec取得<br />　　　　　　if( ++an_tx_count &gt; 7 ) an_tx_count = 0 ;　　　　　　　　　　　　　 // 送信ルートカウンタインクリメント<br />　　　　}<br />　　　　// 待ち時間 無駄にループしても処理負荷が増えるだけなので少しお休み<br />　　　　usleep( 1 ) ;<br />　　}<br />　　// --------- 終 了 ----------<br />　　set_inkey( RESET ) ;　　　　　　// std_inkeyを終了<br />　　close( an_rx ) ;　　　　　　　　// 受信ソケットをクローズ<br />　　close( an_tx ) ;　　　　　　　　// 送信ソケットをクローズ<br />　　printf( &quot;\e〔?25h\e〔0m\n&quot; ) ;　　// コンソール画面を戻す \e〔?25h カーソルの表示<br />　　shmdt( ae_sharemem ) ;　　　　　// 共有メモリの切り離し<br />　　//【開発用】上位モジュールが出来たらそちらで処理する<br />　　shmctl( ae_sharememID, IPC_RMID, 0) ; // 共有メモリ領域開放<br />　　return 0 ;<br />}<br /><br />// ArtDMXのデコード関数<br />int artdmx_decode( char *an_rx_buf, artdmx_t *artdmx_rx ) {<br />　　int i ;<br />　　char int_st〔 sizeof( int ) 〕 ;<br />　　// IDを抽出<br />　　for( i = 0; i &lt; 8; i++ ) {　　　　　　　　　　　　　// bufの先頭から８バイト<br />　　　　artdmx_rx-&gt;id〔 i 〕 = an_rx_buf〔 i 〕 ;　　<br />　　}<br />　　// OpCodeを抽出<br />　　int_st〔 0 〕 = an_rx_buf〔 8 〕 ;<br />　　int_st〔 1 〕 = an_rx_buf〔 9 〕 ;<br />　　int_st〔 2 〕 = 0x00 ;<br />　　int_st〔 3 〕 = 0x00 ;<br />　　artdmx_rx-&gt;opcode = *( ( int * )&int_st〔 0 〕) ;<br />　　if( ! (strcmp( artdmx_rx-&gt;id, &quot;Art-Net&quot; ) == 0　　　　　// ArtDMXかチェックし、そうでなければエラーを返して終了<br />　　　　　　　　&& artdmx_rx-&gt;opcode == 0x5000 ) ) {<br />　　　　return -1 ;<br />　　}<br />　　// ProVerを抽出<br />　　int_st〔 0 〕 = an_rx_buf〔 11 〕 ;<br />　　int_st〔 1 〕 = an_rx_buf〔 10 〕 ;<br />　　int_st〔 2 〕 = 0x00 ;<br />　　int_st〔 3 〕 = 0x00 ;<br />　　artdmx_rx-&gt;prover = *( ( int * )&int_st〔 0 〕) ;<br />　　// Sequenceを抽出<br />　　artdmx_rx-&gt;sequence = an_rx_buf〔 12 〕 ;<br />　　// Physicalを抽出<br />　　artdmx_rx-&gt;physical = an_rx_buf〔 13 〕 ;<br />　　// Universeを抽出<br />　　artdmx_rx-&gt;subnet = an_rx_buf〔 14 〕 / 0x10 ;<br />　　artdmx_rx-&gt;universe = an_rx_buf〔 14 〕 % 0x10 ;<br />　　artdmx_rx-&gt;net = an_rx_buf〔 15 〕 ;<br />　　// Lengthを抽出<br />　　int_st〔 0 〕 = an_rx_buf〔 17 〕 ;<br />　　int_st〔 1 〕 = an_rx_buf〔 16 〕 ;<br />　　int_st〔 2 〕 = 0x00 ;<br />　　int_st〔 3 〕 = 0x00 ;<br />　　artdmx_rx-&gt;length = *( ( int * )&int_st〔0〕) ;<br />　　// Dataを抽出<br />　　for( i = 0; i &lt; artdmx_rx-&gt;length; i++ ) {<br />　　　　artdmx_rx-&gt;data〔 i 〕 = an_rx_buf〔 i + 18 〕 ;<br />　　}<br />　　if( artdmx_rx-&gt;length &lt; 512 ) {<br />　　　　for( i = artdmx_rx-&gt;length; i &lt; 512; i++ ) {<br />　　　　　　artdmx_rx-&gt;data〔 i 〕 = 0x00 ;<br />　　　　}<br />　　}<br />　　return 0 ;<br />}<br /><br />// ArtDMXのエンコード関数<br />int artdmx_encode( char *an_tx_buf, artdmx_t *artdmx_tx ) {<br />　　int i ;<br />　　// IDを設定<br />　　for( i = 0; i &lt; 8; i++ ) {<br />　　　　an_tx_buf〔 i 〕 = artdmx_tx-&gt;id〔 i 〕 ;<br />　　}<br />　　// OpCodeを設定<br />　　an_tx_buf〔 8 〕 = (char)( artdmx_tx-&gt;opcode % 0x100 ) ;<br />　　an_tx_buf〔 9 〕 = (char)( artdmx_tx-&gt;opcode / 0x100 ) ;<br />　　// ProVerを設定<br />　　an_tx_buf〔 10 〕 = (char)( artdmx_tx-&gt;prover / 0x100 ) ;<br />　　an_tx_buf〔 11 〕 = (char)( artdmx_tx-&gt;prover % 0x100 ) ;<br />　　// Sequenceを設定<br />　　an_tx_buf〔 12 〕 = (char) artdmx_tx-&gt;sequence ;<br />　　// Physicalを設定<br />　　an_tx_buf〔 13 〕 = (char) artdmx_tx-&gt;physical ;<br />　　// SubUniを設定<br />　　an_tx_buf〔 14 〕 = (char)( artdmx_tx-&gt;subnet * 0x100 + artdmx_tx-&gt;universe ) ;<br />　　// Netを設定<br />　　an_tx_buf〔 15 〕 = (char)artdmx_tx-&gt;net ;<br />　　// Lengthを設定<br />　　an_tx_buf〔 16 〕 = (char)( artdmx_tx-&gt;length / 0x100 ) ;<br />　　an_tx_buf〔 17 〕 = (char)( artdmx_tx-&gt;length % 0x100 ) ;<br />　　// Dataを設定<br />　　memcpy( an_tx_buf + 18, artdmx_tx-&gt;data, 512 ) ;<br />　　return 0 ;<br />}<br /><br />// ArtDMXのチェック用画面表示<br />int artdmx_check_disp( artdmx_t *artdmx, char *key_code_st, int *key_code_length_st,<br />　　　　　　　　　　unsigned long long int *val1, unsigned long long int *val2 ) {<br />　　// 汎用変数<br />　　//int i ;<br />　　// タイムカウント変数<br />　　struct timespec now ;　　　　　　　　　　　　　 // 現在POSIX時を得る構造体<br />　　unsigned long long int now_nsec ;　　　　　　　 // 現在nsecを保存<br />　　static unsigned long long int prev_nsec = 0 ;　 // 過去nsecを保存<br />　　// データ管理用<br />　　static artdmx_t artdmx_disp ;<br />　　// std_dump 用変数<br />　　static int first_line = 0 ;　　　　　　　　　　 // 表示開始行数<br />　　// 表示制御変数<br />　　struct winsize ws ;<br />　　static int col = 20 ;<br />　　static int row = 100 ;<br />　　static int net = 0 ;<br />　　static int subnet = 0 ;<br />　　static int universe = 0 ;<br /><br />　　// カーソルキー入力<br />　　if( *key_code_length_st &gt; 0 ) {<br />　　　　if( strcmp( key_code_st, _KEY_RIGHT ) == 0 ) {<br />　　　　　　if( ++universe &gt; 7 ) universe = 7 ;<br />　　　　}<br />　　　　if( strcmp( key_code_st, _KEY_LEFT ) == 0 ) {<br />　　　　　　if( --universe &lt; 0 ) universe = 0 ;<br />　　　　}<br />　　　　if( strcmp( key_code_st, _KEY_UP ) == 0 ) {<br />　　　　　　first_line-- ;<br />　　　　}<br />　　　　if( strcmp( key_code_st, _KEY_DOWN ) == 0 ) {<br />　　　　　　first_line++ ;<br />　　　　}<br />　　　　*key_code_length_st = 0 ;<br />　　}<br />　　// 対象ユニバースのデータをスタック<br />　　if( ( artdmx-&gt;net == net ) && ( artdmx-&gt;subnet == subnet ) && ( artdmx-&gt;universe == universe ) ) {<br />　　　　memcpy( &artdmx_disp, artdmx, sizeof( artdmx_t ) ) ;<br />　　}<br /><br />　　// タイムカウント<br />　　clock_gettime( CLOCK_REALTIME, &now ) ;　　　　　　　　　　　　 // 現在POSIX時間値取得<br />　　now_nsec = ( unsigned long long int )now.tv_sec * 1e9　　　　　 // unsigned long long int型(8バイト長int)変数に<br />　　　　　　　　+ now.tv_nsec ;　　　　　　　　　　　　　　　　　　 // 取得値をひとまとめにする(nsec)<br />　　if( now_nsec - prev_nsec &lt; 5e7) return -1 ;　　　　　　　　　　 // 経過時間が不足なら何もせずリターン<br />　　prev_nsec = now_nsec ;　　　　　　　　　　　　　　　　　　　　　// 過去nsecを現在値としておく<br />　　// 画面のテキスト表示サイズを取得<br />　　ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) ;　　　　　　　　　　　　 // 画面サイズを取得 幅=ws.ws_col 高=ws.ws_row<br />　　if( row + 4 &gt; ws.ws_row ) row = ws.ws_row - 4 ;　　　　　　　　 // dumpの行数制限<br />　　// artdmxを表示<br />　　printf( &quot;\e〔0;0H&quot; ) ;　　　　　　　　　　　　　　　　　　　　　　　　　 // カーソルを左上に　 <br />　　printf( &quot;Sender&#58; %s&#58;%d&quot;, artdmx_disp.senderip, artdmx_disp.senderport ) ;<br />　　printf( &quot;\e〔28GID&#58; %s&quot;, artdmx_disp.id ) ;<br />　　printf( &quot;\e〔41GOpCode&#58; 0x%04X&quot;, artdmx_disp.opcode ) ;<br />　　printf( &quot;\e〔57GProVer&#58; 0x%04X&quot;, artdmx_disp.prover ) ;<br />　　printf( &quot;\e〔0K\nSequence&#58; 0x%04X&quot;, artdmx_disp.sequence ) ;<br />　　printf( &quot;\e〔19GPhysical&#58; 0x%04X&quot;, artdmx_disp.physical ) ;<br />　　printf( &quot;\e〔37GLength&#58; %d&quot;, artdmx_disp.length ) ;<br />　　printf( &quot;\e〔50G&lt; Net&#58;%d SubNet&#58;%d Universe&#58;%d &gt;\e〔0K\n&quot;, artdmx_disp.net, artdmx_disp.subnet, artdmx_disp.universe ) ;<br />　　dump_print( artdmx_disp.data, artdmx_disp.length, col, row, &first_line, 0 ) ;<br />　　printf( &quot;%8lld /%8lld nsec&quot;, *val1, *val2 ) ;<br />　　//fflush( stdout ) ;<br />　　// 終了<br />　　return 0 ;<br />}</span></small><br /><br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%41%72%74%2d%4e%65%74" class="taglink" title="Art-Net">#&#91;Art-Net&#93;</a> <a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%ef%bc%a3%e8%a8%80%e8%aa%9e" class="taglink" title="Ｃ言語">#Ｃ言語</a> -- Posted by 電装工芸 〔12336文字〕 ]]></description>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=1059</link>
	<guid>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=1059</guid>
	<category>tegalog</category>
	<pubDate>Fri, 06 Jun 2025 12:59:08 +0900</pubDate>
</item>
<!-- One Entry Data for RSS Feed -->
<item>
	<title><![CDATA[ 　SharedMemory(共有メモリ)であるmmapの使い… ]]></title>
	<description><![CDATA[ 　SharedMemory(共有メモリ)であるmmapの使い方が整理出来つつあります。<br />　検証はこれからですが、理解出来たところをオレメモとして書いておきます。<br />　あくまで「オレメモ」です。間違いアリアリでよろしくお願いします。<br />　なお、mmapには様々な用法あるらしい。下記はプロセス間の共有メモリに限った使い方です。<br /><small class="decorationS"><span class="decorationF deco-code">/* mmapを使うためのライブラリ */<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;sys/mman.h&gt;<br /><br />/* 共有メモリにテキストを代入する */<br />char *st;　　　　// 扱うデータの型でmmapのポインタを設定<br />int msize = 4096;<br />st = mmap( NULL, msize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 );　　// ここまでやってからfork()でプロセスを分ける<br />*st = &apos;TEST&apos;;　　　　// mmapに「TEST」が代入される(変数をポインタで扱う方法で扱える)<br /><br />/* 使用後は共有メモリを解放する */<br />munmap( st, msize );<br /><br />mmapの引数<br />１つ目(addr/NULL)：mmapを定義するメモリアドレスを設定する項目だが、NULLにしておけばOSが決めてくれる。<br />２つ目(size/msize)：確保するメモリサイズの指定。ページメモリのサイズの倍数にするベシというご意見と、欲しいメモリサイズを指定すればOSが調整してくれるというご意見など色々ある。変数の型からsizeofで得る方法(sizeof(int)など)を使われている方もいる。<br />３つ目(prot/PROT_READ | PROT_WRITE)：読み書きモードを設定する。この書き方だと読み書き両方可能にする。<br />４つ目(flag/MAP_ANON | MAP_SHARED)：MAP_ANONはファイルをマッピングせずに使う指定(共有メモリとして使うだけならこれでいい)、MAP_SHAREDはプロセス間で共有するという指定。<br />５つ目(fd/-1)：ファイルディスクリプタの指定だが、上記でMAP_ANONにしているので-1で無しとする。<br />６つ目(offset/0)：スタートアドレスからどれくらいずらしたところを使うか。<br /><br />　共有メモリは読み書きのタイミングをマネージしれくれませんので、何かしらの管理をしないといけません。<br /><br />参考：ページメモリのサイズを取得する<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;unistd.h&gt;<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;stdio.h&gt;<br />long page_size = sysconf( _SC_PAGESIZE );</span></small><br /><br />　ついでにpipeも。<br />　ただし、ここではpipe2(Linux固有)を使います。pipeの上位互換で引数でノンブロッキングの設定が出来るからです。通常のpipeはパイプが空の場合に有効なデータが取り出せるまで待ってしまいますがO_NONBLOCKを設定すると待ちません。<br />　なお、以前の書き込みでpipeは単純なスタックと書きましたが、Queue程マネジメントされていないFIFOです。訂正します。<br /><small class="decorationS"><span class="decorationF deco-code">/* pipeを使うためのライブラリ */<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%64%65%66%69%6e%65" class="taglink" title="define">#define</a> _GNU_SOURCE　　// よくわからないけど必要なおまじない？<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;fcntl.h&gt;　　// O_*(ここではO_NONBLOCK) 定数の定義の取得<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a> &lt;unistd.h&gt;　　// pipeの本体を呼ぶ<br /><br />/* pipeの定義 */<br />int pipefd&#91;2&#93;;　　　// ファイルディスクリプタとしてint配列を用いる 変数の名前は任意<br />if( pipe2( pipefd, O_NONBLOCK ) &lt; 0 ) {　　// ファイルディスクリプタとする配列とノンブロッキングのフラグを引数にする<br />　// pipe2の戻り値が-1なら設定エラー<br />}<br /><br />/* pipeへの書き込み */<br />char *st = &quot;TEST&quot;;<br />write( pipefd&#91;1&#93;, st, strlen( st ) );　　// strlenは&lt;string.h&gt;が必要。成功なら書き込んだバイト数、失敗なら-1が戻る。<br /><br />/* pipeからの読み出し */<br />char buf&#91;128&#93;;<br />read( pipefd&#91;0&#93;, &buf, sizeof( buf ) );　　// パイプが空の場合はEOFを得るか戻り値が0になると思われる。成功なら読み取ったしたバイト数、失敗なら-1が戻る。<br /><br />/* pipeを閉じる(fork()して読み出し側書き込み側に分かれる場合はfork()した後に使わない側を閉じて運用する。もちろん終了する際にはすべて閉じる) */<br />close( pipefd&#91;0&#93; );　　// 読み出しを閉じる<br />close( pipefd&#91;1&#93; );　　// 書き込みを閉じる<br /><br />　int配列pipefdは&#91;0&#93;が読み出し&#91;1&#93;が書き込みになるファイルディスクリプタ。<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%64%65%66%69%6e%65" class="taglink" title="define">#define</a> MEMREAD 0<br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%64%65%66%69%6e%65" class="taglink" title="define">#define</a> MEMWRITE 1<br />　などとして使うとわかりやすいかも。<br /><br />　OSに寄りますが、スタック長は65536バイトが一般的らしい。<br />　pipeは読み書きのタイミングをマネージしてくれます。</span></small> <br /><br />　どちらもファイルを読み書きする手法を応用していますので、ファイルの読み書きの仕方を勉強しなおしてから取り組むとわかりやすいかもしれません。<br /><br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%ef%bc%a3%e8%a8%80%e8%aa%9e" class="taglink" title="Ｃ言語">#Ｃ言語</a> -- Posted by 電装工芸 〔2308文字〕 ]]></description>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=838</link>
	<guid>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=838</guid>
	<category>tegalog</category>
	<pubDate>Wed, 20 Mar 2024 12:47:27 +0900</pubDate>
</item>
<!-- One Entry Data for RSS Feed -->
<item>
	<title><![CDATA[ 　ホール管理の増員で操作盤の置物になっているだけなので調べモ… ]]></title>
	<description><![CDATA[ 　ホール管理の増員で操作盤の置物になっているだけなので調べモノをし放題です。<br /><br />　PythonのライブラリをＣ言語で作る方法の基本はわかりました。<a class="url" href="https&#58;//daeudaeu.com/python-c-call/" target="_blank" title="https&#58;//daeudaeu.com/python-c-call/">このサイト</a>だけでほぼ解決。<br /><br />　製作手順を大まかに書き出すと、<br /><br />１）関数ライブラリを用意する。<br />　Ｃ言語で<a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%69%6e%63%6c%75%64%65" class="taglink" title="include">#include</a>して使える関数なら汎用でも自作でも何でもいい。<br />２）「ラッパー関数」を用意する。<br />　Ｃ言語の関数をPythonへ引き渡す定義をするソースファイル。Pythonからの呼び出し方と変数の変換方法をＣ言語で記述します。<br />３）セットアップファイルを用意する。<br />　セットアップファイルはgccで言うところのMakeFileです。Pythonで記述され、ファイル名はsetup.pyにすることが多いそうです。<br />４）ビルドする。<br />　セットアップファイルを使ってビルドする。<br />５）インストールする。<br />　セットアップファイルを使ってインストールする（動作の実際はPythonパッケージ管理のpipへの登録）。<br /><br />　と、なります。<br />　ラッパー関数はＣ言語とPythonの両方を知らないと記述出来ないので少し難しいですが、セットアップファイルは定型の通り記述するだけです。<br /><br /><a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%ef%bc%a3%e8%a8%80%e8%aa%9e" class="taglink" title="Ｃ言語">#Ｃ言語</a> <a href="https&#58;//www.densokogei.jp/tegalog/tegalog.cgi?tag=%50%79%74%68%6f%6e" class="taglink" title="Python">#Python</a> -- Posted by 電装工芸 〔524文字〕 ]]></description>
	<link>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=549</link>
	<guid>https://www.densokogei.jp/tegalog/tegalog.cgi?postid=549</guid>
	<category>tegalog</category>
	<pubDate>Sat, 08 Apr 2023 10:18:53 +0900</pubDate>
</item>

	<!-- END ENTRIES -->
</channel>
</rss>

