'노트/Programming D'에 해당되는 글 5건

  1. D언어에서의 함수 포인터 2011.06.25
  2. 변수에 void를 대입하는 문장의 의미. 2011.06.22
  3. D언어에서 typedef는 alias가 아니다 2010.10.29
  4. Visual D (5) 2010.10.07
  5. D Programming Language (2) 2010.01.11
D1에서는 아래와 같은 C스타일 함수포인터 선언이 가능했다.
typedef int (*functionName) (int a, int b);


D2부터는 C스타일의 함수 포인터 선언이 불가능해지고 D스타일 함수 포인터만을 사용해야 한다. (D2에서 typedef가 폐기된 영향으로 추측된다) 선언 형식은 다음과 같다.

alias [반환형] function ([매개변수 목록]) [이름];

대리자 포인터의 경우 function 대신 delegate를 사용하면 된다. 선언한 함수 포인터 변수에는 일반적인 함수의 주소, 또는 함수 리터럴을 대입할 수 있다. 함수 포인터 변수에 대리자 리터럴을 담을 수는 없다.

 
alias int function(string b) func;

int foo(string b)
{
	writeln(b);
	
	return 0;
}

void main()
{
	func f;
	
	f = &foo;
	
	f("hello D!");
	
	f = function(string b)
	{
		writeln(b);
		return 1;
	};
	
	f("hello D!");
}

D의 모든 내장 형식은 .init 속성에 기본값을 가지고 있으며 변수가 선언되면 메모리가 기본값으로 초기화된다. 이는 변수를 초기화하지 않고 사용하더라도 런타임에 문제가 발생하지 않도록 돕는 장치이다. 다음 코드를 보자. (표준 라이브러리를 사용하기 위한 import선언은 배제한다.)

void main()
{
   int a;
   writeln(a);
}

위 코드에서는 a가 int.init, 즉 0 으로 초기화되어 0이 출력된다. 그렇다면 a에 void를 대입하면 어떻게 될까.

void main()
{
   int a = void;
   writeln(a);
}

위 코드의 실행 결과 a는 쓰레기 값이 된다. 변수의 자동 초기화는 초기화되지 않은 변수가 부주의하게 사용되는 경우를 대비한 D의 배려이므로, 만약 변수가 생성당시 초기화되지 않았더라도 사용되기 전에 어떤 값으로 초기화되는 것이 보장되는 경우에는 불필요한 오버헤드가 된다. 이 때 변수에 void를 대입함으로서 자동 초기화 기능을 변수 생성 과정에서 배제할 수 있다. 이 기능은 단일한 내장 형식 뿐 아니라 배열, 구조체에도 동일하게 적용된다.

//배열의 경우
int[3] getarray()
{
	int[3] array = void;
	
	foreach(i, ref a; array)
		a = i;
	
	return array;
}

//구조체의 경우
struct S { int a; bool b; }

void getByRef(ref S s)
{
	s.a = 123;
	s.b = true;
}

void main()
{
	S s = void;
	getByRef(s);
	writeln(s.a, s.b);
}

C에서의 typedef는 단지 특정 형식에 대해 별칭을 만드는 것 뿐이었다. 따라서 다음과 같은 코드는 컴파일 에러가 발생했다.

typedef int HANDLE;

int foo(int);
int foo(HANDLE);

하지만 D에는 C의 typedef에 해당하는 alias라는 키워드가 존재한다. 물론 완전히 같은 기능은 아니다. alias는 타입에 대한 것 뿐 아니라 네임스페이스, 변수 등 모든 심볼에 대해 사용이 가능하다. 우선 C와 D의 typedef 키워드가 어떻게 다른지 명백하게 보여주는 샘플 코드를 보기로 하자.

import std.stdio;

typedef int INT; // int에 대해 typedef를 사용했다.

int main(string[] argv)
{
	writefln("foo(int) = %d, foo(INT) = %d", foo(2), foo(cast(INT)2));
	readln(); //키보드 입력을 기다린다.
	return 0;
}

int foo(int i) //D는 전방선언이 필요하지 않다.
{
	return i ^^ 2; //pow연산자이다. i의 2제곱.
}

int foo(INT i) //오버로딩된다.
{
	return 0;
}


D에서는 위와 같이 int를 typedef한 INT라는 타입을 int와는 별개의 타입으로 취급한다. 따라서 오버로딩이 가능해진다. 위 샘플에서는 foo(INT)를 호출하기 위해 2를 INT타입으로 캐스팅했다. 위 코드에서 typedef를 alias로 바꿔 보자.

만약 해당 함수들에 대한 호출이 없었다면 일단 컴파일러는 에러를 내지 않는데, 링커에 가서 기존에 정의된 심볼이라는 내용의 에러가 뜨게 된다. DMD는 일단 시그니처가 같더라도 에러로 취급하지 않는 것으로 보인다. 이 부분은 조금 문제가 있어 보이기도 하지만, 호출이 존재하면 지정된 시그니처에 해당하는 함수가 여러 개 매칭된다는 내용의 에러가 컴파일시 뜨게 된다.


보다 나아가서, 결론적으로:
typedef는 D2에서 deprecated다.
Tag // Programming D

Visual D

from 노트/Programming D 2010.10.07 14:13

Visual Studio에 D를 통합시키는 플러그인. 문서 작성 현재 0.3버전이며 지속적으로 업데이트되고 있는 몇 안되는 D용 IDE이다. 다른 하나는 D-IDE이며 .NET 4.0기반의 독자적인 IDE환경을 구축하고 있다. 이쪽도 사용하려면 못할 것은 없지만 일단 윈도우 개발자에게 VS보다 익숙한 환경은 없으므로 VisualD가 최근 선호되는 경향이다. (대표적인 멀티미디어 API 바인딩인 Derelict도 VisualD용 프로젝트 파일을 제공하고 있다)

 

다만 개발환경을 구축하는 작업이 꽤 불편한데, 틈틈이 정보를 수집해서 외부 라이브러리를 바인딩하는데 성공하기까지도 상당한 시간이 소요되었다. 알아낸 바, D 개발환경 구축에는 다음과 같은 준비물이 필요하다.

Visual Studio 2008,2010

DMD

VisualD

유감스럽게도 언어의 확장은 Visual Studio에서만 지원하는 것이기 때문에 MS가 제공하는 각 대표적 언어별 Express버전에서는 Visual D를 사용할 수 없다.

위 순서대로 준비물들을 설치한다. 특히 DMD는 경로작성의 편의성을 위해 드라이브 루트에 근접한 디렉토리에 설치하는 것이 현명하다.

최종적으로 Visual D를 설치한 후 환경설정에 들어간다.

 

도구-옵션-프로젝트 및 솔루션 트리를 열어보면 Visual D Settings가 보인다. VisualD 설치 당시 정확한 DMD의 경로를 제공했다면 대부분의 설정은 되어있을 것이다.

Import paths는 C의 인클루드 디렉토리와 같다. Library paths는 이름 그대로이다. 나머지 것들은 건드릴 필요가 없다.

 

이걸로 설정이 끝날 수 있다면 좋겠지만, 아직 문제가 몇 가지 남아있다.

관련 프로젝트들의 포럼에 따르면 현재 DMD 컴파일러가 IDE가 제공하는 컴파일 메니페스트에서 import path 및 library path를 DMD기본 설정 파일인 sc.ini의 설정으로 덮어써버리는 듯 하다.

그래서 프로젝트에 필요한 경로들을 IDE에서 지정해도 해당 모듈을 찾을 수 없다거나 링크할 심볼을 찾을 수 없다거나 하는 메시지만 뜨게 될 것이다.

 

VIsualD 개발자는 (DMD설치경로)/windows/bin/sc.ini에 기록된 기본 스위치에 설정을 추가할 것을 권한다.

 

LIB="%@P%\..\lib";\dm\lib;%DMD_LIB% <- 링크시 라이브러리를 찾을 경로에 VisualD가 제공하는 경로를 추가한다.

DFLAGS="-I%@P%\..\..\src\phobos" "-I%@P%\..\..\src\druntime\import" -ID:\SDK\Derelict2\import <-IDE가 어찌할 수 없으므로 import 경로를 직접 추가할 것.

 

이제 IDE에서 필요한 lib파일을 추가해 줄 수 있는데, C와는 달리 lib파일을 세미콜론이 아닌 공백으로 구분한다. 이점은 상당히 중요하다. 이에 대한 정보를 찾지 못해 오래 헤맸다.

필요한 라이브러리를 추가해주고 빌드하면 성공하는 모습을 볼 수 있다.

--

정정. 문제는 DMD가 아니라 DigitalMars가 제공하는 링커인 OPTLINK에 있는 것으로 보인다. 여전히 도구-프로젝트 및 솔루션-Visual D Settings에 설정된 Import Path는 인식하지 못하지만 각 프로젝트별로 설정되는 Additional Imports의 경로는 문제없이 인식한다. (Visual D 개발자의 의도인지는 불분명)

그러나 라이브러리 경로는 프로젝트에 설정하더라도 여전히 링커에 전달되지 않으므로 sc.ini에 환경변수 DMD_LIB를 유지해야 한다.




참고로 Additional Imports에 주어지는 경로 역시 공백으로 구분된다. 디렉토리 경로에 공백이 들어갈 경우 위와 같이 경로를 큰따옴표로 감싸 주자.




--


여담 :

과거에 국내에서 동일한 이름의 프로젝트를 진행하시던 분이 있었다. D 1.x를 대상으로 하는 IDE였고 한번 돌려본 기억만 나는데 문득 생각나서 찾아보니 프로젝트가 폐기 된 것 같다. 이 링크는 유일하게 남아있는 기록.

원문링크>http://www.digitalmars.com/d/index.html

D는 시스템 프로그래밍 언어이다. 이것은 C와 C++의 강력함과 고성능에 루비나 파이썬같은 현대 언어들의 생산성을 더하는 데 중점을 두었다. 주목할 점은 품질관리(QA)의 필요성, 문서화, 관리, 이식성과 신뢰성이다.

D언어는 정적 타입을 갖고, 기계어로 직역된다. 또한 여러 패러다임과,  명령형, 객체지향, 메타프로그래밍 같은 다양한 프로그래밍 스타일을 지원한다. D는 C문법 계열 언어들의 일원이며, 그 외견은 C++과 매우 유사해 보인다. 여기(todo:번역예정)에 특징의 목록이 있다.

D는 기업적인 의도나 그 어떠한 프로그래밍 이론에도 지배되지 않는다. D가 나아가는 방향은 D 프로그래밍 커뮤니티의 요구사항과 기여에 의해 정해진다.

D언어에는 두 가지 버전이 있다.

  1. 안정화된 버전 1
  2. 차세대이며 현재 개발중인 버전 2

D의 구현은 현재 4가지가 존재한다.
  1. Digital Mars dmd 의 Windows, x86 Linux, Max OSX 10.5, x86 FreeBSD를 위한 ver 1, 2
  2. LLVM D 컴파일러 ver 1
  3. GNU D 컴파일러 GDC, Windows, Mac OSX를 포함한 몇몇 플랫폼을 위한 ver 1.30, 2.014
  4. D.NET 컴파일러 알파, ver 2

거대하며, 지속적으로 성장하고 있는 D 소스코드와 프로젝트들의 모음집은 dsource에 있다. 열거할수 없는 D 위키와 라이브러리, 도구, 미디어 관련 문서 등은 dlink에 있다.

이 문서는 pdf로도 제공된다. 일본어, 포르투갈어 번역도 있다. 독일어 서적 Programming in D: Introduction to the new Programming Language 이 출판되었다. 또한 일본어 서적 D Language Perfect Guide도 있다.

이것은 D의 일부 기능성들의 실제 예를 보여주는 샘플이다.

이하, 원문참조.