找回密码
 欢迎注册
查看: 5596|回复: 0

[分享] 单文件混合语言编程

[复制链接]
发表于 2013-1-15 23:35:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
今天阅读了GMP的代码,发现许多有趣的东西,看到了一种在一个文件中混合多种语言的技巧。这里的混合语言编程不是指C中嵌入汇编语言的那种,C中嵌入汇编语言还是符合某种C编译器语言语法的。这里的混合语言具有这样的特点,文件类型是A语言源代码,但在文件中A嵌入B语言源代码。比如
     
  1. 批处理中嵌入perl代码,下面的例子是我的一个老大(美国人)写的。这里的关键是"#!Perl/bin/perl -w" 和 "%perl% -x %0 %*" 这2句. 第2句使用参数 -x 调用自己,按照perl命令行参数的规则,则#!Perl前的代码将忽略。

-----------------------------------
@rem = '--*-Perl-*--
@echo off
rem is perl on path?
perl -v > nul 2>&1
if %errorlevel% equ 0 (
set perl=perl
) ELSE (
set perl=c:\svg_cygwin_db\bin\perl.exe
)
if "%OS%" == "Windows_NT" goto WinNT
echo PERL=%perl%
%perl% -x "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
%perl% -x %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
if %errorlevel% == 9009 echo You do not have Perl in your PATH.
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperl
@rem ';
#!Perl/bin/perl -w
#line 22

use FindBin qw(\$RealDir);
use lib "\$RealDir/lib";

use RTH;

RTH::run();

__END__
:endofperl
------------------------------------------------


2.shell脚本中嵌入c语言源代码。
   这是在GMP源码包中的config.guess中看到了。这个文件的类型是shell脚本,从第一句"#! /bin/sh" 可以看出。但在这个文件文件中混入许多c代码。例如:"cat >\$dummy.c <<\EOF" 下面的行就是标准的c代码,直到EOF为止,在EOF下面的代码则是将这段c代码编译并运行编译好的程序。
---------------------------------------------------------------
dummy=my_test
cat >\$dummy.c <<\EOF
#include <stdio.h>
struct {
  int   n;  /* force 4-byte alignment */
  char  a[8];
} getpvr = {
  0,
  {
    0x7c, 0x7f, 0x42, 0xa6,  /* mfpvr r3 */
    0x4e, 0x80, 0x00, 0x20,  /* blr      */
  }
};
int
main ()
{
  unsigned  (*fun)();
  unsigned  pvr;

  /* a separate "fun" variable is necessary for gcc 2.95.2 on MacOS,
     it gets a compiler error on a combined cast and call */
  fun = (unsigned (*)()) getpvr.a;
  pvr = (*fun) ();

  switch (pvr >> 16) {
  case 0x0001: puts ("powerpc601");  break;
  case 0x0003: puts ("powerpc603");  break;
  case 0x0004: puts ("powerpc604");  break;
  case 0x0006: puts ("powerpc603e"); break;
  case 0x0007: puts ("powerpc603e"); break;  /* 603ev */
  case 0x0008: puts ("powerpc750");  break;
  case 0x0009: puts ("powerpc604e"); break;
  case 0x000a: puts ("powerpc604e"); break;  /* 604ev5 */
  case 0x000c: puts ("powerpc7400"); break;
  case 0x0041: puts ("powerpc630");  break;
  case 0x0050: puts ("powerpc860");  break;
  case 0x8000: puts ("powerpc7450"); break;
  case 0x8001: puts ("powerpc7455"); break;
  case 0x8002: puts ("powerpc7457"); break;
  case 0x8003: puts ("powerpc7447"); break; /* really 7447A */
  case 0x800c: puts ("powerpc7410"); break;
  }
  return 0;
}
EOF
if (\$CC_FOR_BUILD \$dummy.c -o \$dummy) >/dev/null 2>&1; then
    # This style construct is needed on AIX 4.3 to suppress the SIGILL error
    # from (*fun)().  Using \$SHELL -c ./\$dummy 2>/dev/null doesn't work.
    { x=`./\$dummy`; } 2>/dev/null
    if test -n "\$x"; then
      exact_cpu=\$x
    fi
fi
-----------------------------------------------------------------------------------------------------------------------------


注意:由于本论坛会对美元符号解释为公式,故文中所有的美元符号都写成斜杠加美元符号。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-24 08:31 , Processed in 0.059780 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表