Programmingの最近のブログ記事

自分用メモ

共有メモリ
→複数のプロセスやスレッドから扱うことのできるメモリ空間のこと。本当であれば後述するsemaphoreやmutexで排他処理をすべきだが、しなくても大丈夫という報告もある。要確認。
semaphore(セマフォ)
→排他処理のこと。ある処理をする際に、セマフォのフラグを取得したプロセス(又はスレッド)のみが扱うことができるようにする機構で、そのフラグの数は1から設定することが可能。
mutex(ミューテックス)
→排他処理のこと。簡単に言うと先のセマフォのフラグを1に設定したのと同じ。
まだXSのことをよくわかってないのですが、XSモジュール用のModule::Setupのflavorを作ってみました。

このflavorを使うには、記事下にあるコードをXSFlavor.pmって名前でファイルに保存して、

% module-setup --init --flavor-class=+XSFlavor xs

でflavorを展開したら、あとは以下のようにするだけでXSモジュールの雛形ができあがります。

% module-setup Your::Module xs

このflaverでできる雛形のXSには、newとincrementっていう関数が最初から追加されているので、いらない場合はてきとうに編集してください。


このflavorを最初はModule::Starterで作ろうと思ってたんだけど、module-starterコマンドではflavorの使い分ける機能がないんですね。自分でそういうコマンドラインのを作ればいいんだけど、もうその機能が備わってるModule::Setupに切り替えちゃいました。

Module::Setupのflavor機能は素晴しいすなぁ。

以下がFlavorになります。

package XSFlavor;
use strict;
use warnings;
use base 'Module::Setup::Flavor';
1;

=head1

XSFlavor - pack from xs

=head1 SYNOPSIS

  XSFlavor-setup --init --flavor-class=+XSFlavor new_flavor

=cut

__DATA__

---
file: .shipit
template: |
  steps = FindVersion, ChangeVersion, CheckChangeLog, DistTest, Commit, Tag, MakeDist, UploadCPAN
  svk.tagpattern = release-%v
---
file: ____var-module_file-var____.xs
template: |
  #ifdef __cplusplus
  extern "C" {
  #endif
  #include "EXTERN.h"
  #include "perl.h"
  #include "XSUB.h"
  #include "ppport.h"
  #ifdef __cplusplus
  }
  #endif
  
  typedef SV * [% module.replace('::', '_')%];
  
  MODULE = [% module %]		PACKAGE = [% module %]		
  
  [% module.replace('::', '_') %]
  new(...)
      INIT:
      	char *classname;
  	/* get the class name if called as an object method */
  	if ( sv_isobject(ST(0)) ) {
  	    classname = HvNAME(SvSTASH(SvRV(ST(0))));
  	}
  	else {
  	    classname = (char *)SvPV_nolen(ST(0));
  	}
  
      CODE:
      	/* This is a standard hash-based object */
      	RETVAL = ([% module.replace('::', '_') %])newHV();
  
  	/* Single init value */
  	if ( items == 2 ) 
  	    hv_store((HV *)RETVAL, "value", 5, newSVsv(ST(1)), 0);
  	/* name/value pairs */
  	else if ( (items-1)%2 == 0 ) {
  	    int i;
  	    for ( i=1; i < items; i += 2 ) {
  		hv_store_ent((HV *)RETVAL, ST(i), newSVsv(ST(i+1)), 0);
  	    }
  	}
  	/* odd number of parameters */
  	else {
  	    Perl_croak(aTHX_
  		"Usage: [% module %]->new()\n"
  		"    or [% module %]->new(number)\n"
  		"    or [% module %]->new(key => value, ...)\n"
  	    );
  	}
  
      OUTPUT:
      	RETVAL
  
  IV
  increment(obj)
      [% module.replace('::', '_') %] obj
  
      INIT:
         RETVAL = 0;
         if ( items > 1 )
             Perl_croak(aTHX_ "Usage: [% module %]->increment()");
  
      CODE:
         SV **svp;
         if ((svp = hv_fetch((HV*)obj, "value", 5, FALSE))) {
             RETVAL = SvIV(*svp);
             RETVAL++;
             hv_store((HV *)obj, "value", 5, newSViv(RETVAL), 0);
         }
      OUTPUT:
         RETVAL
---
file: Changes
template: |
  Revision history for Perl extension [% module %]
  
  0.01    [% localtime %]
          - original version
---
file: Makefile.PL
template: |+
  use inc::Module::Install;
  
  name     '[% dist %]';
  all_from 'lib/[% module_path %].pm';
  
  # requires '';
  
  tests 't/*.t';
  author_tests 'xt';
  
  cc_inc_paths '.';
  can_cc or die 'This module requires a C compiler';
  
  build_requires 'Test::More';
  use_test_base;
  auto_include;
  WriteAll;
  
  sub MY::post_constants {
      return <<"POST_CONST";
  XSUBPPARGS += -typemap typemap
  POST_CONST
  }

---
file: MANIFEST.SKIP
template: |
  \bRCS\b
  \bCVS\b
  ^MANIFEST\.
  ^Makefile$
  ~$
  ^#
  \.old$
  ^blib/
  ^pm_to_blib
  ^MakeMaker-\d
  \.gz$
  \.cvsignore
  ^t/9\d_.*\.t
  ^t/perlcritic
  ^tools/
  \.svn/
  ^[^/]+\.yaml$
  ^[^/]+\.pl$
  ^\.shipit$
---
file: README
template: |
  This is Perl module [% module %].
  
  INSTALLATION
  
  [% module %] installation is straightforward. If your CPAN shell is set up,
  you should just be able to do
  
      % cpan [% module %]
  
  Download it, unpack it, then build it as per the usual:
  
      % perl Makefile.PL
      % make && make test
  
  Then install it:
  
      % make install
  
  DOCUMENTATION
  
  [% module %] documentation is available as in POD. So you can do:
  
      % perldoc [% module %]
  
  to read the documentation online with your favorite pager.
  
  [% config.author %]
---
file: typemap
template: |
  ###############################################################################
  ##
  ##    Typemap for [% module %] objects
  ##
  ##    Copyright (c) [% config.author %]
  ##    All rights reserved.
  ##
  ##    This typemap is designed specifically to make it easier to handle
  ##    Perl-style blessed objects in XS.  In particular, it takes care of
  ##    blessing the object into the correct class (even for derived classes).
  ##
  ##
  ###############################################################################
  ## vi:et:sw=4 ts=4
  
  TYPEMAP
  
  [% module.replace('::', '_') %] T_PTROBJ_SPECIAL
  
  INPUT
  T_PTROBJ_SPECIAL
      if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")) {
  	$var = SvRV($arg);
      }
      else
  	croak(\"$var is not of type ${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")
  
  OUTPUT
  T_PTROBJ_SPECIAL
      /* inherited new() */
      if ( strcmp(classname,\"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\") != 0 )
  	$arg = sv_bless(newRV_noinc($var),
  	    gv_stashpv(classname,TRUE));
      else
  	$arg = sv_bless(newRV_noinc($var),
  	    gv_stashpv(\"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\",TRUE));
---
file: lib/____var-module_path-var____.pm
template: |
  package [% module %];
  
  use strict;
  use warnings;
  #use base qw(Exporter);
  #our @EXPORT_OK = ();
  
  our $VERSION = '0.01';
  
  require XSLoader;
  XSLoader::load(__PACKAGE__, $VERSION);
  
  1;
  __END__
  
  =head1 NAME
  
  [% module %] -
  
  =head1 SYNOPSIS
  
    use [% module %];
  
  =head1 DESCRIPTION
  
  [% module %] is
  
  =head1 AUTHOR
  
  [% config.author %] E<lt>[% config.email %]E<gt>
  
  =head1 SEE ALSO
  
  =head1 LICENSE
  
  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself.
  
  =cut
---
file: t/00_compile.t
template: |
  use strict;
  use Test::More tests => 1;
  
  BEGIN { use_ok '[% module %]' }
---
file: xt/01_podspell.t
template: |
  use Test::More;
  eval q{ use Test::Spelling };
  plan skip_all => "Test::Spelling is not installed." if $@;
  add_stopwords(map { split /[\s\:\-]/ } <DATA>);
  $ENV{LANG} = 'C';
  all_pod_files_spelling_ok('lib');
  __DATA__
  [% config.author %]
  [% config.email %]
  [% module %]
---
file: xt/02_perlcritic.t
template: |
  use strict;
  use Test::More;
  eval {
      require Test::Perl::Critic;
      Test::Perl::Critic->import( -profile => 'xt/perlcriticrc');
  };
  plan skip_all => "Test::Perl::Critic is not installed." if $@;
  all_critic_ok('lib');
---
file: xt/03_pod.t
template: |
  use Test::More;
  eval "use Test::Pod 1.00";
  plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
  all_pod_files_ok();
---
file: xt/perlcriticrc
template: |
  [TestingAndDebugging::ProhibitNoStrict]
  allow=refs
---
plugin: plugin.pm
template: |
  package XSFlavor::Plugin;
  use strict;
  use warnings;
  use base 'Module::Setup::Plugin';
  use Devel::PPPort;
  use File::Spec;
  
  sub register {
      my $self = shift;
      $self->add_trigger( after_create_skeleton => \&create_ppport_process );
      $self->add_trigger( after_setup_template_vars => \&add_template_vars );
  }
  
  sub create_ppport_process {
      my $self = shift;
      $self->log( "Creating ppport.h" );
      Devel::PPPort::WriteFile(
          File::Spec->catfile( $self->distribute->dist_path, 'ppport.h' )
      );
  }
  
  sub add_template_vars {
      my ( $self, $template_vars ) = @_;
      my ( $module_file ) = $template_vars->{ module } =~ m#(?:.*::)?(.*)$#;
      $template_vars->{ module_file } = $module_file;
  }
  
  1;
---
config:
  plugins:
    - Config::Basic
    - Template
    - Test::Makefile
    - Additional
    - +XSFlavor::Plugin
あるC言語で書かれたプログラムのソースを見ててu_intとかu_charとかいう方があって、これってなんだろうと思ったので調べてみた。

Mac OS X(Leopard)だと/usr/include/sys/types.hに答えが。

typedef unsigned char           u_char;
typedef unsigned short          u_short;
typedef unsigned int            u_int;

なるほど。unsigned intやunsigned charのエイリアスなんだね。

ちなみにCentOSとTurboLinuxだと/usr/include/sys/types.hには

typedef __u_char u_char;
typedef __u_short u_short;
typedef __u_int u_int;

と書いてあって、__u_charとかは/usr/include/bits/types.hに

typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;

って書いてありました。

$foo = qr/blah/;

こんなときの$fooをなんて名前にするのか。

ちょっと気になったので聞いてみた。




今これを書いてる段階では$regexが優勢ですね。

自分はいつも$regexか$regexpか悩むんだけど、誰かが選択肢に追加した$reとかちょっと好きかも。

でもこの$で始まる書き方だと言語が限定されちゃうから聞きかたをちょっと間違えた感あり…。

興味があったら答えてください。
なんかのソース(たしかmod_dosdetector)を読んでてCにtmpnam()ってのがあるのを知りました。

なんの関数なんだろうとman tmpnamで調べたらテンポラリーファイル用の関数でした。
プログラムでテンポラリーのファイルを使う場合の名前をよしなに
決定してくれるものらしく、stdio.hで定義されています。
使い方は↓こんな感じにするとs[]にファイル名が入るみたい。
#include <stdio.h>

int main()
{
    char s[L_tmpnam+1];
    tmpnam(s);
    printf("%s\n", s);
    return 0;
}

ためしに実行してみると、
% gcc ./tmpnam_test.c
% ./a.out
/var/tmp/tmp.0.GYj9KF

こんな感じ。あーなんかこのファイル名どこかで見たことあるような…。

上のコードのL_tmpnamってのを配列の大きさにつかってるんだけど、
これもstdio.hに定義されています(Mac OS XやFreeBSDの場合はstdio.h、
CentOSだとbits/stdio_lim.hに定義されていました)。
Mac OS Xだとパスの最大長と同じバイトになってました。


ちなみにCentOSでtmpnam()を使おうとしたら、
% gcc tmpnam_test.c
/tmp/ccwelnuR.o(.text+0x24): In function `main':
: warning: the use of `tmpnam' is dangerous, better use `mkstemp'

って怒られた。デンジャラスだってぇえぇえぇ!

mkstemp()を使えと言ってるので調べてみたら、これも同じような用途に使う関数らしい。 manによると以下のような感じで使うらしい。
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char template[] = "/tmp/fileXXXXXX";
    int fd;
    FILE *fp;

    fd = mkstemp(template);

    if ((fp = fdopen(fd, "w")) == NULL)
        exit(1);

    fprintf(fp, "temp test\n");
    fclose(fp);
    return 0;
}

こうすると「temp test」って内容の/tmp/fileXXXXXX(XXXXXXは毎回違う)という
ファイルが作成されるようだ。

なるほど。
なんかのときに使えそうなので覚えておこう。

仕事でlibgdを使う機会があっていろいろ見てたのですがlibgdではbmpを扱うことができないません。
なんでやねんと思いつつ、libgdでbmpを扱う方法を探した結果libgdのcvsにbmpに対応しようとしている欠片を見つけました。

http://cvs.php.net/viewcvs.cgi/gd/playground/gdbmp/
(※今見たら2008年03月にも更新がされていたりするので、現在のファイルであればもしかしたら動くかもしれません。残念ながら自分が見たときには動きませんでした。)

喜び勇んでこれを取り込んでみたのですがうまく動きませんでした…。しかたがないので、上記のプログラムを元に自分でいろいろ修正をして動くようにしました。せっかくなのでpatchを公開しておきます。

ちなみに、このpatchは2.0.35用ですのでご注意ください。
(もうすぐ2.0.36がリリースされそうなのですけどね…。)

あと以下のBTSでBMPの話題も出ていて、サポートしそうな雰囲気もありますし、先に紹介したcvsのファイルも更新が続けられているので、ここで公開するpatchはそれまでのつなぎということで。

http://bugs.libgd.org/?do=details&task_id=61

言うまでもないですが、at your own riskでお願いします。

patchは以下。

ちょっと前からFlex SDKで使って、ActionScript3を書いて遊んでます。そうこうしていたらApolloなんか出てきて、おぉなんてナイスタイミングと思いApolloでairを作ったりもしています。

そこで、Flex SDKをちょっとだけ使った雑感とおすすめリンクを。

Flex SDKの良いところ:
  • インストールが簡単
  • → SDKをダウンロードしてきて解凍するだけ
  • コマンドラインで扱える
  • → コンパイラにasファイルを指定してコンパイルすると、swfが出来る
  • ネットワーク関係や動画関係のやりたいことは一通りできる
  • → もちろんflvのストリーミングとか簡単にできるし、XMLのパースもできるし、他にもいろんなことできます。
  • 文法が簡単
  • →オブジェクト指向がわかってればすんなり入れそう
Flex SDKの悪いところ:
  • ばりばりデザイン的なのは苦手そう(自分ができないだけかも)
  • 大規模なswfの開発は向かなそう(自分がまだわかってないのかも)
  • デバッグがめんどい
こんな感じです。あとリファレンスがネット上にしかない(これ)っぽいんだけど、あのリファレンスをダウンロードできないのかな?このリファレンスのページが重くてかなわない。ローカルに置いておきたいのだが。。。

あといくつかオススメページをご紹介します。 とりあえず、なんかできたらここで紹介していきたいと思います。

検索

広告

OpenID対応しています OpenIDについて
Powered by Movable Type 4.22-ja