안드로이드 어플들을 소개하는 사이트...

http://www.androlib.com

다운로드를 받을 수 있는 건 아니고,
안드로이드 마켓의 어플들을 소개, Feeding 을 해주네요...


안드로이드 어플 다운로드 사이트들은....

http://devian.tistory.com/129
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,
기본적으로 안드로이드 SDK에는 안드로이드 마켓이 빠져있지만
Dev폰의 system 이미지 (system.img) 파일을 포팅함으로써
AVD에서도 안드로이드 마켓을 이용할 수 있습니다..

수정 방식은 android SDK의 platfroms 폴더에 각 버전별 android 데이터가 있는데...
이중 images 폴더의 system.img 를 교체한 후 avd를 생성함으로써 가능합니다.

참고로 dev 폰의 초기 설정 과정에서 슬라이드를 올리라고 나오는 부분이 있는데...
Ctrl+F11을 누르면  Landscape 모드로 바뀌며 슬라이드를 올린 것으로 인식이 되네요...

[이미지]
1.5 (cupcake) : http://www.kandroid.org/download/system.img 
1.6 (donut) : http://www.4shared.com/file/165624746/fc72c3ed/system.html

1.6에서 안드로이드 마켓이 많이 업그레이드 되었는데....
2.0용 이미지도 빨리 나오길 기대해보네요...^^

Android 1.5 용(cupcake) Android Market

Android 1.6 (donut)용 Android Market

[참고] kandroid.org

http://www.kandroid.org/board/board.php?board=androidmarket&command=body&no=17
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,
현재 Android SDK 버전은 r04....
설치 방법도 심플해졌다...
http://developer.android.com/sdk/index.html

하지만 여전히  ADK Manager에서 AVD(Android Virtual Device) 생성 시
한글 계정 문제로 생성이 제대로 되지 않는다....ㅜ.ㅜ

이를 위해 Android SDK Manager가 아닌 command line에서 수동 생성을 해 주어야 한다.

먼저 다음 명령을 실행해서 생성 가능한 타겟을 조회한다.

D:\dev\android-sdk-windows\tools\android list target

결과 중에 다음 내용 확인할 수 있다.

id: 2 or "android-3"
     Name: Android 1.5
     Type: Platform
     API level: 3
     Revision: 1
     Skins: HVGA (default), HVGA-L, HVGA-P, QVGA-L, QVGA-P

해당 내용을 기반으로 avd를 수동 생성해주면 된다.

android create avd -t 2 -n cupcake -p D:\dev\avd\cupcake


추가 샘플
    ex) Google Maps를 지원하고, 1GB의 SD카드를 장착한 Android 1.5 기기에 해당하는 AVD의 생성명령입니다.
          android create avd -n mapSd1.5 -t 3 -c 1024M

    ex) QVGA가로모드의 스킨을 가지는 AVD의 생성명령입니다. -s 옵션으로 지정합니다.
          android create avd -n QVGA-L1.5 -t 2 -s QVGA-L

    ex) 2GB의 SD카드를 가진 AVD를 생성하는 명령입니다. -c 옵션으로 지정합니다.
          android create avd -n vanilla1.5w2GigSD -t 2 -c 2048M
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,
안드로이드 어플을 웹을 통해 다운로드 받을 수 있는 곳....
apk 파일 다운 받아서 adb 이용하면 쉽게 설치가 가능하다...

설치 방법 안내


http://www.androidfreeware.org/

http://androidsoftwaredownload.com/

http://www.handango.com/


많은 어플들이 donut 에서 조차 오류 (INSTALL_PARSE_FAILED_MANIFEST_MALFORMED)가 나는 걸 보면
버전이 안맞는 경우가 많은 듯.....
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,


오늘은 Android 개발 환경 설정 및 Hello World 까지.......

1) Eclipse 다운로드 및 설치(
http://www.eclipse.org/downloads/)


2) ADT 다운로드 및 압축 해제(http://developer.android.com/sdk/1.5_r3/index.html)
3) Eclipse에 ADT Plug-in 설치
    - 메뉴 > Help > Install New Software > 아래 URL 넣고 진행
      https://dl-ssl.google.com/android/eclipse/

4) ADT SDK 설정
   - 메뉴 > Window > Preference > Android > SDK 위치 설정 후 Apply -> OK
     (Mac에서는 Window 가 아닌 Eclipse 란다.....Window 란 표현을 쓰지 않는 세심한 배려??)

5) AVD(Android Virtual Device) 생성
   - 메뉴 > Window > Android AVD Manager , 또는 toolbar의 핸셋 버튼 > Create AVD

6) 프로젝트 생성
    - 메뉴 > File > New > Other > Android > Android Project

7) 코드 수정
   - HelloAndroid.java  수정
package com.android.helloandroid;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Hello, Android");
setContentView(tv);

}
}

8) 실행
  - Run > Run As > Android Application
* 여기서 상당한 인내심을 발휘해야 한다.
2~3분 정도 기다리면 꽤 그럴듯한 실제 단말 바탕화면이 뜨고 곧 해당 어플을 실행시켜준다.


블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,


TCHAR szItem[256];

TVITEM tvItem;
tvItem.cchTextMax = 256;
tvItem.pszText = szItem;
tvItem.mask = TVIF_TEXT | TVIF_HANDLE;

HTREEITEM hItem = m_ctrlTree.GetRootItem();

while ( hItem )
{
 tvItem.hItem = hItem;
 m_ctrlTree.GetItem( &tvItem );

 TRACE( _T("%s\n"), tvItem.pszText );

 if ( m_ctrlTree.ItemHasChildren( hItem ) )
 {
  HTREEITEM hSubItem = m_ctrlTree.GetChildItem( hItem );

  while ( hSubItem )
  {
   tvItem.hItem = hSubItem;
   m_ctrlTree.GetItem( &tvItem );

   TRACE( _T("--- %s\n"), tvItem.pszText );

   hSubItem = m_ctrlTree.GetNextSiblingItem( hSubItem );
  }
 }

 hItem = m_ctrlTree.GetNextSiblingItem( hItem );
}

블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,

사실 Visual Basic(이하 VB) 에 대해서는 잘 모릅니다...;;; (물론, 지금도 마찬가지구요...)

이번에 일을 하면서, 조금 공부하게 된 부분이 있어서 올려봅니다.

회사에서 제가 개발을 하고 있는 부분은 어떻게 보면 중간모듈입니다...

제가 만든 제품 자체가 엔드유저에게 바로 제공되는 것이 아니라....

엔드유저가 사용하게 되는 제품을 개발할 때... 제가 만든 라이브러리/모듈을 쓰거든요;;

저는 C/C++ 로 라이브러리/모듈을 개발하고... 이 라이브러리를 쓰는 업체에서도

대부분은 C/C++ 로 작업을 합니다.
.
.

근데 한번씩... 예외적으로 C/C++ 이 아닌 다른 언어를 쓰는 경우가 있습니다.

델파이랑 VB가 그 대표적인 경우인데요;;;..

이번에 VB를 사용하는 업체에서 라이브러리를 쓰겠다고 요청이 왔습니다;;;..

만약, C/C++ 업체라면 라이브러리 파일(*.LIB)과 헤더파일(*.H), 메뉴얼을 보내주면서..

"작업하다가~~ 문의사항 있음 연락하세요~~" 이러면 되는데...;;;

다른 언어의 경우는 이게 참 힙듭니다..;;

이럴때 DLL 이란게 참~~ 도움이 되는데요...

라이브러리와 동일한 기능을 수행하는 DLL 을 만들어두고... 다른 언어의 경우에는

그 DLL 을 제공하면 되는거죠~~ㅋ

-0-;; 샘플코드를 제공해달라고 하는데..-0- VB는 잘 쓰질 못하고... 난감한 상황에서;;

부랴부랴 이것저것 뒤져가며 결국엔 익혔답니다..;;


#define TEST_DLL extern "C" __declspec(dllexport)

// 1. 'int' Return
TEST_DLL int Test_Sum(int Num1, int Num2);

// 2. 'void' Return
TEST_DLL void Test_Output();

// 3. 'void*' Return
TEST_DLL void* CreateUser();

DLL 에는 위와 같은 함수들이 들어있고, 이 함수들을 VB에서 사용하려면...

먼저 아래와 같이 선언을 해줘야 합니다.

' 1. 'int' Return
Declare Function Test_Sum Lib "TestDll.dll" (ByVal Num1 As Integer, ByVal Num2 As Integer) As Integer

' 2. 'void' Return
Declare Sub Test_Output Lib "TestDll.dll" ()

' 3. 'void*' Return
Declare Function CreateUser Lib "TestDll.dll" () As Int32

기본틀은....

Declare [Function / Sub] <FunctionName> Lib "<DLL Name>" (인자들) (As 반환값)

요렇습니다...


그리고 함수 선언문을 작성할 때 알아둬야 되는 몇가지 사항들입니다.

1. 해당함수가 리턴하는 값이 없는 경우(void 형 함수)에는 Sub 를 사용한다.
2. 함수의 인자가 값을 넘겨주는 경우는 ByVal 을 주소값(포인터)를 넘겨주는 경우는 ByRef를 사용한다.
3. 선언의 제일 마지막에는 해당함수의 리턴형태를 As 를 사용해서 지정해준다.
    void* 함수처럼 포인터를 리턴하는 경우는 해당 바이트의 수에 맞는 데이터형을 지정한다.
    ( DLL 에서 32비트 데이터로 리턴을 하면 VB에서도 32비트 데이터형으로 받는다. )

선언이 끝나면 코드에서 사용이 가능한데 사용방법은 C/C++ 에서 함수의 사용과 비슷합니다.

단, Sub 로 선언한 함수의 경우는 Call 명령으로 호출해주도록 합니다.
(ex. Call Test_Output() )
.
.

이런식으로 C++ 로 만들어진 DLL을 VB에서도 사용이 가능합니다.

더 세밀한 내용은 저도 잘 모르는 관계로.. 요정도 선에서 수박겉핥기 정도로..ㅋㅋ
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,
AnimateWindow

윈도우에 효과를 주어 사라지고 등장하게 해 주는 API 이다.

[Flash] http://neodreamer.tistory.com/attachment/cfile5.uf@125F4F1149CF8A02438DC4.swf



함수 설명 ( 출처 : MSDN )
Syntax

BOOL AnimateWindow(
HWND hwnd,
DWORD dwTime,
DWORD dwFlags
);

Parameter 설명 보기


첫 번째 인자인 hwnd 는 효과를 적용하기위한 윈도우의 핸들이다.

두 번째 인자인 dwTime 은 지정된 효과를 수행할 시간으로 밀리세컨드 단위로 입력한다. 입력값이 작을 수록 에니메이션 효과의 시간이 짧아 지므로 에니메이션이 빠르게 동작한다.

세 번째 인자는 효과의 종류이다.
  • AW_SLIDE : 기본 인자로 에니메이션 효과를 의미하며 생략해도 슬리이딩 효과가 있는 것 같다. AW_CENTER 가 함께 적용되면 무시된다.
  • AW_ACTIVATE : 윈도우을 활성화 한다. AW_HIDE와 사용하지 않는다.
  • AW_BLEND : Fading 효과
  • AW_HIDE : 윈도우를 사라지게 한다.
  • AW_CENTER : 윈도우의 가운데 점을 기준으로 효과를 적용한다.
  • AW_HOR_POSITIVE : 윈도우를 좌에서 우로 사라지게 또는 보이게 함.
  • AW_HOR_NEGATIVE : 윈도우를 우에서 좌로 사라지게 또는 보이게 함.
  • AW_VER_POSITIVE : 윈도우를 위에서 아래로 사라지게 또는 보이게 함.
  • AW_VER_NEGATIVE : 윈도우를 아래에서 위로 사라지게 또는 보이게 함.
아래 소스는 이 글 위에 포함되어 있는 플래시를 만들면서 작성한 코드이다.
01.//---------------------------------------------------------------------------
02.void __fastcall TfrmMain::btnBlendClick(TObject *Sender)
03.{
04.    // Blending
05.    AnimateWindow( Handle, 1000, AW_HIDE | AW_BLEND );
06.    Sleep(1000);
07.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_BLEND );
08.}
09.//---------------------------------------------------------------------------
10.void __fastcall TfrmMain::btnCenterClick(TObject *Sender)
11.{
12.    // Center
13.    AnimateWindow( Handle, 1000, AW_HIDE | AW_CENTER );
14.    Sleep(1000);
15.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_CENTER );
16.}
17.//---------------------------------------------------------------------------
18.void __fastcall TfrmMain::btnHPosClick(TObject *Sender)
19.{
20.    // Horizontal Positive
21.    AnimateWindow( Handle, 1000, AW_HIDE | AW_HOR_POSITIVE );
22.    Sleep(1000);
23.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_HOR_POSITIVE );
24.}
25.//---------------------------------------------------------------------------
26.void __fastcall TfrmMain::btnHNegClick(TObject *Sender)
27.{
28.    // Horizontal Negative
29.    AnimateWindow( Handle, 1000, AW_HIDE | AW_HOR_NEGATIVE );
30.    Sleep(1000);
31.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_HOR_NEGATIVE );
32.}
33.//---------------------------------------------------------------------------
34.void __fastcall TfrmMain::btnVPosClick(TObject *Sender)
35.{
36.    // Vertical Positive
37.    AnimateWindow( Handle, 1000, AW_HIDE | AW_VER_POSITIVE );
38.    Sleep(1000);
39.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_VER_POSITIVE );
40.}
41.//---------------------------------------------------------------------------
42.void __fastcall TfrmMain::btnVNegClick(TObject *Sender)
43.{
44.    // Vertical Negative
45.    AnimateWindow( Handle, 1000, AW_HIDE | AW_VER_NEGATIVE );
46.    Sleep(1000);
47.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_VER_NEGATIVE );
48.}
49.//---------------------------------------------------------------------------
50.void __fastcall TfrmMain::btnHPosVPosClick(TObject *Sender)
51.{
52.    AnimateWindow( Handle, 1000, AW_HIDE | AW_HOR_POSITIVE | AW_VER_POSITIVE );
53.    Sleep(1000);
54.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_HOR_POSITIVE | AW_VER_POSITIVE );
55.}
56.//---------------------------------------------------------------------------
57.void __fastcall TfrmMain::btnHNegVNegClick(TObject *Sender)
58.{
59.    AnimateWindow( Handle, 1000, AW_HIDE | AW_HOR_NEGATIVE | AW_VER_NEGATIVE );
60.    Sleep(1000);
61.    AnimateWindow( Handle, 1000, AW_SLIDE | AW_HOR_NEGATIVE | AW_VER_NEGATIVE );
62.}
63.//---------------------------------------------------------------------------

블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,





Firefox Plug-in – JavaScript 연동 (4)

JavaScript에서 Plug-in 내부의 함수를 호출하는 방법을 익혀 봅니다. 서로 다른 형태의 바이너리가 소통할 수 있는 이유는 XPCOM이라는 인터페이스 규약을 따르고 있기 때문입니다.

IDL 파일 생성


그림 1 Add 함수

지금 만들어 보려고 하는 형태는 위 그림에서 설명하는 것처럼 1 + 2를 호출하면 3을 반환하는 함수를 만들어 보려고 하고 있습니다. Function Call처럼 보이는 Add 함수는 Plug-in이 구현하고 있는 함수로서 JavaScript가 호출해서 반환 값을 얻어가고 있는 형태인데요. 바이너리 레벨에서 서로 통신하는 구조는 내부적으로 XPCOM 인터페이스 규칙을 따르고 있기 때문에 가능합니다.

간단해 보이는 Add 함수를 구현함으로써 크게 XPCOM 함수를 구현하는 방법, XPCOM 인터페이스를 구현하는 방법, 인자가 넘어오는 형태, 반환 값을 넘기는 형태 등을 배울 수 있습니다.

가장 첫 번째 단계로 IDL 파일을 만들어 봅시다. IDL 파일은 Interface Description Language로 인터페이스를 정의하는 파일이 되겠습니다. 인터페이스가 필요한 이유는 Add 함수가 어떤 형태로 구현이 되어 있던 간에 외부에서는 인터페이스만 보고 통신할 수 있도록 하기 위함입니다.


그림 2 nsIScriptableObject.idl

위 그림에 작성된 IDL 파일을 보면 #include 부분과 uuid 부분을 제외하면 Class 정의하는 것과 거의 차이가 없어 보입니다. Add 함수는 long 형 2개를 인자로 받고 long형을 반환하는 함수의 형태입니다. 위 내용을 그대로 작성해서 nsIScriptableObject.idl 파일로 저장합니다.


Type Header와 Type Library 파일 생성

앞서 배웠던 xpidl을 이용해서 Type Header와 Type Library를 생성합니다.

xpidl -m header -I .\gecko-sdk\idl nsIScriptableObject.idl
xpidl -m typelib -I .\gecko-sdk\idl nsIScriptableObject.idl

결과 파일로 nsIScriptableObject.h 와 nsIScriptableObject.xpt 파일이 생성됩니다.


Scriptable Object 구현 (XPCOM 프로그래밍)

nsIScriptableObject.h 파일에는 Add 함수에 대한 정의 부분만 들어가 있습니다. 내용을 잠시 보면

... 생략

/* Use this macro when declaring classes that implement this interface. */
#define NS_DECL_NSISCRIPTABLEOBJECT \
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval);

/* Use this macro to declare functions that forward the behavior of this interface to another object. */
#define NS_FORWARD_NSISCRIPTABLEOBJECT(_to) \
  NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { return _to Add(a, b, _retval); }

/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
#define NS_FORWARD_SAFE_NSISCRIPTABLEOBJECT(_to) \
NS_IMETHOD Add(PRInt32 a, PRInt32 b, PRInt32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Add(a, b, _retval); }

… 생략


위 와 같은 내용으로 이루어져 있습니다. Xpild이 자동으로 생성해주는 부분이기 때문에 많은 부분 생략되었습니다. 중요한 부분은 NS_DECL_NSISCRIPTABLEOBJECT 이라고 선언되어 있는 매크로 입니다. Xpidl이 자동으로 헤더 파일을 생성할 때 개발자가 구현을 쉽게 할 수 있도록 몇가지 매크로를 만들어 주는데요. NSISCRIPTABLEOBJECT은 개발자가 구현해야할 함수 원형을 매크로로 선언해놓은 부분입니다. 본 예에서는 함수가 하나밖에 없기 때문에 불필요해 보일 수도 있지만 실제로 헤더에 선언된 매크로들은 많은 편리함을 제공해줍니다.

이 헤더파일의 구현부를 작성해보도록 합시다. 구현 파일의 이름은 nsScriptableObject.h와 nsScriptableObject.cpp로 하겠습니다.

Step 1. nsScriptableObject 클래스를 만들고
Step 2. xpidl이 생성한 nsIScriptableObject 를 상속받습니다.
Step 3. 그 다음에는 AddRef, Release, QueryInterface 함수를 구현해줍니다.
(이 3함수들을 XPCOM 규약에 따르는 형식입니다.)
Step 4. 그리고 마지막으로 Add 함수를 구현해줍니다.

nsScriptableObject.h 파일을 살펴보겠습니다.
#include "nsIScriptableObject.h"

class nsScriptableObject  : public nsIScriptableObject
{
public:
nsScriptableObject();
virtual ~nsScriptableObject();

public:
// native methods callable from JavaScript
NS_DECL_NSISCRIPTABLEOBJECT


///////////////////////////////////////////////////////
// XPCOM Support
///////////////////////////////////////////////////////

// methods from nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();

protected:
nsrefcnt m_nRefCnt;

};

NS_DECL_NSISCRIPTABLEOBJECT은 Add 함수의 원형이 들어있는 매크로 입니다. 그리고 아래는 AddRef, Release, QueryInterface 함수가 선언되어 있습니다.

nsScriptableObject.cpp 파일을 살펴보겠습니다.
// AddRef, Release and QueryInterface are common methods and must
// be implemented for any interface
NS_IMETHODIMP_(nsrefcnt) nsScriptableObject::AddRef()
{
++m_nRefCnt;
return m_nRefCnt;
}

NS_IMETHODIMP_(nsrefcnt) nsScriptableObject::Release()
{
--m_nRefCnt;
if (m_nRefCnt == 0)
{
delete this;
return 0;
}
return m_nRefCnt;
}

static NS_DEFINE_IID(kIScriptableIID, NS_ISCRIPTABLEOBJECT_IID);
static NS_DEFINE_IID(kIClassInfoIID, NS_ICLASSINFO_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);

// here nsScriptablePeer should return three interfaces it can be asked for by their iid's
// static casts are necessary to ensure that correct pointer is returned
NS_IMETHODIMP nsScriptableObject::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if(!aInstancePtr)
return NS_ERROR_NULL_POINTER;

if(aIID.Equals(kIScriptableIID)) {
*aInstancePtr = static_cast<nsIScriptableObject*>(this);
AddRef();
return NS_OK;
}

if(aIID.Equals(kIClassInfoIID)) {
*aInstancePtr = static_cast<nsIClassInfo*>(this);
AddRef();
return NS_OK;
}

if(aIID.Equals(kISupportsIID)) {
*aInstancePtr = static_cast<nsISupports*>(static_cast<nsIScriptableObject*>(this));
AddRef();
return NS_OK;
}

  return NS_NOINTERFACE;
}

NS_IMETHODIMP nsScriptableObject::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval)
{
int nResult = a + b ;

*_retval = nResult ;

return NS_OK;
}

AddRef, Release, QueryInterface 함수는 위 내용대로 구현하면 됩니다. 자세한 내용은 추후에 알아보도록 합니다.

Add 함수 구현부를 보면 인자로 a, b , _retval 이 있습니다. a와 b는 idl에서 선언해준 그대로의 형태로 되어 있으며, 반환값은 정수형 포인터로 _retval 로 지정되어 있는 것을 볼 수 있습니다. 일반 Function Call과 약간은 다른 형태로 보입니다.


nsIClassInfo 구현

JavaScript에서 Plug-in 함수를 호출을 허용하기 위해서는 nsIClassInfo를 상속받아야 합니다.


// We must implement nsIClassInfo because it signals the
// Mozilla Security Manager to allow calls from JavaScript.
#include "nsIClassInfo.h"
class nsClassInfoMixin : public nsIClassInfo
{
  // These flags are used by the DOM and security systems to signal that
  // JavaScript callers are allowed to call this object's scritable methods.
  NS_IMETHOD GetFlags(PRUint32 *aFlags)
  {*aFlags = nsIClassInfo::PLUGIN_OBJECT | nsIClassInfo::DOM_OBJECT;
    return NS_OK;}
  NS_IMETHOD GetImplementationLanguage(PRUint32 *aImplementationLanguage)
  {*aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS;
    return NS_OK;}
  // The rest of the methods can safely return error codes...
  NS_IMETHOD GetInterfaces(PRUint32 *count, nsIID * **array)
  {return NS_ERROR_NOT_IMPLEMENTED;}
  NS_IMETHOD GetHelperForLanguage(PRUint32 language, nsISupports **_retval)
  {return NS_ERROR_NOT_IMPLEMENTED;}
  NS_IMETHOD GetContractID(char * *aContractID)
  {return NS_ERROR_NOT_IMPLEMENTED;}
  NS_IMETHOD GetClassDescription(char * *aClassDescription)
  {return NS_ERROR_NOT_IMPLEMENTED;}
  NS_IMETHOD GetClassID(nsCID * *aClassID)
  {return NS_ERROR_NOT_IMPLEMENTED;}
  NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
  {return NS_ERROR_NOT_IMPLEMENTED;}
};


#include "nsIScriptableObject.h"
class nsScriptableObject  : public nsIScriptableObject ,
     public nsClassInfoMixin
{

.. 생략

위 같이 nsClassInfoMixin 클래스를 작성해주시고, 구현한 nsScriptableObject 클래스에 상속을 시켜주세요. 이제 JavaScript에서 Plug-in에 있는 함수를 호출할 때 사용할 함수에 대한 구현이 완료되었습니다. 다음은 plug-in에서 ScriptableObject를 Firefox 브라우저에 넘겨주는 코드가 작성되어야 합니다.




CleanSample에서 GetValue 함수 추가 구현

이전에 작성하였던 CleanSample에서는 GetValue함수가 구현이 되어 있지 않습니다. 이 함수를 구현해야 Firefox 브라우저에게 ScriptableObject를 넘길 수가 있고, 그제서야 JavaScript에서 Plug-in 내부의 함수를 호출 할 수 있게 됩니다.

가장 먼저 fillPluginFunctionTable 함수에서 GetValue 함수 포인터를 넘겨주는 코드를 수정합니다.
static NPError fillPluginFunctionTable(NPPluginFuncs* aNPPFuncs)
{
  if(aNPPFuncs == NULL)
  return NPERR_INVALID_FUNCTABLE_ERROR;

  // Set up the plugin function table that Netscape will use to
  // call us. Netscape needs to know about our version and size  
  // and have a UniversalProcPointer for every function we implement.

  aNPPFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
  aNPPFuncs->newp          = NPP_New;    // 플러그인 인스턴스가 생성될때마다 호출된다.
// aNPPFuncs->destroy       = NPP_Destroy;   // 플러그인 인스턴스가 소멸될때마다 호출된다.
  aNPPFuncs->setwindow     = NPP_SetWindow;   // 플러그인의 윈도우 상태가 변경될때마다 호출된다.
// aNPPFuncs->newstream     = NPP_NewStream;
// aNPPFuncs->destroystream = NPP_DestroyStream;
// aNPPFuncs->asfile        = NPP_StreamAsFile;
// aNPPFuncs->writeready    = NPP_WriteReady;
// aNPPFuncs->write         = NPP_Write;
// aNPPFuncs->print         = NPP_Print;
// aNPPFuncs->event         = NPP_HandleEvent;
// aNPPFuncs->urlnotify     = NPP_URLNotify;
  aNPPFuncs->getvalue      = NPP_GetValue;
// aNPPFuncs->setvalue      = NPP_SetValue;

  return NPERR_NO_ERROR;
}

그리고 다음으로 NPP_GetValue 함수를 구현합니다. 함수 내용은 대략적으로 Firefox가 ScriptableObject의 인스턴스를 요청처리와 Interface 요청 처리하는 코드로 구성되어 있습니다.
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
if(instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;

NPError rv = NPERR_NO_ERROR;

if (variable == NPPVpluginScriptableInstance)
{
// addref happens in getter, so we don't addref here
nsScriptableObject * scriptablePeer = getScriptablePeer();
if (scriptablePeer)
{
  *(nsScriptableObject **)value = scriptablePeer;
}
else
{
  rv = NPERR_OUT_OF_MEMORY_ERROR;
}  
}

else if (variable == NPPVpluginScriptableIID)
{
static nsIID scriptableIID = NS_ISCRIPTABLEOBJECT_IID;
nsIID* ptr = (nsIID *)NPNFuncs.memalloc(sizeof(nsIID));

if (ptr)
{
  *ptr = scriptableIID;
  *(nsIID **)value = ptr;
}
else
{
  rv = NPERR_OUT_OF_MEMORY_ERROR;
}
}
return rv ;
}


작동개시!


ㅋ ㅑ ~ 에러없이 컴파일이 되는데 성공하셨나요? 저는 여기까지 오는데 무수한 삽질을 했습니다;; 마지막으로 Firefox에서 돌려보면서 결과를 보는 일만 남았습니다. 아래와 같은 HTML 페이지를 작성하신 다음에 %Firefox 설치 폴더%plugins 폴더에 NPPlugIn.dll 파일과 NPPlugIn.xpt 파일을 복사하신 다음 HTML 페이지를 Firefox로 열어보세요.

<embed id=sample type="application/sample-plugin" width=600 height=40>


<script>
var obj = document.getElementById( "sample" ) ;
var result = obj.Add( 2 , 1 ) ;
alert( result ) ;
</script>


후후후! Alert 창으로 1 + 2 = 3 의 결과 창이 뜨는 것이 보이시나요? 이제 plug-in 뭐 별거냐 싶으시죠?

 

 
본 글의 출처는 다음과 같습니다.

작성자 : 이은규
홈페이지 : http://unkyulee.net
작성일 : 2006-02-20
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,


들어는 봤나! Firefox PlugIn (3)

30줄도 안 되는 PlugIn을 작성해보자.

PlugIn SDK를 다운받으면 샘플 코드가 있습니다. 헌데, 샘플 코드 치고는 워낙 신중을 기했는지 샘플이 약간 어렵게 보입니다. 더 쉽게 작성할 수도 있는데 말 입니다. 그래서 최소한의 조건을 갖춘 Hello World 플러그인을 작성해보려고 합니다.

함수 3개로 이루어진 DLL 프로젝트 입니다. 쉽겠죠? 프로젝트 설정하는 부분의 분량이 좀 많아서 그렇지, 코드 내용은 상당히 가볍습니다. 가벼운 만큼 플러그인 코드를 이해하기 쉽겠죠? 자신만의 플러그인을 만들어 보세요!

Step 1 ) NPTest 프로젝트 생성
- Win32 Dynamic-Link Library를 만듭니다.
- A Simple DLL Project를 선택
- 주의! : FireFox는 파일명이 NP로 시작하는 것만 인식합니다.

Step 2 ) DLLMain 함수 삭제
- NPTest.cpp 에서 DLLMain 함수 삭제
- #include “npplat.h” 추가

Step 3 ) include 디렉토리 설정
- SDK 폴더에서 gecko-sdk와 sdk 폴더를 프로젝트 내에 include 폴더를 생성한 뒤 복사 합니다.
- Project Setting의 C/C++ 탭에서 Project 옵션 창에 다음 정보를 추가합니다.

/I ".\include\sdk\samples\include"
/I ".\include\gecko-sdk\plugin\include"
/I ".\include\gecko-sdk\nspr\include"
/I ".\include\gecko-sdk\java\include"

Step 4 ) 계속해서 Project Setting에서 C++/C 탭에 다음정보를 추가합니다.
- Preprocessor definition에 MOZILLA_STRICT_API,XP_WIN,_X86_ 항목을 추가한다.

Step 5 ) def 파일 생성
- NPTest.def 파일 추가 (파일 -> New -> C++ Source -> NPTest.def )

NPTest.def 파일의 내용을 다음과 같이 정의하세요.
LIBRARY   NPTEST

EXPORTS
NP_GetEntryPoints   @1
NP_Initialize       @2
NP_Shutdown         @3

Step 6 ) NPTest.cpp 에 함수 추가
NP_GetEntryPoints, NP_Initialize, NP_Shutdown 함수를 추가합니다.

NPTest.cpp 파일의 내용에 다음 내용을 추가하세요.
NPError OSCALL NP_Shutdown()

return NPERR_NO_ERROR;
}

NPError OSCALL NP_Initialize(NPNetscapeFuncs* aNPNFuncs)

AfxMessageBox( "hi" ) ;
return NPERR_NO_ERROR;
}

NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* aNPPFuncs)
{
return NPERR_NO_ERROR;
}

Step 7) Version 리소스를 생성합니다.

FireFox가 플러그인을 인식하기 위해서는 정확한 버전 정보를 생성해야 합니다. 이때 버전정보가 지켜야 할 규칙이 있는데 이를 명심하고 작성해야 합니다.

규칙1. 버전 정보는 English (US)로 설정되어야 합니다.
규칙2. Character Type은 Multilingual 로 설정되어야 합니다.
규칙3. FileEntents, MIMEType가 명시되어야 합니다.

리소스 추가 -> Version 을 한 뒤 Property 창에서 버전 정보를 English(US)로 설정합니다. 또한 프로젝트 세팅에서 Resource 탭에서 언어를 영어(미국)으로 설정합니다. 새로운 버전 블록을 추가할 때 English(US)로 설정하고 코드 페이지는 Multilingual로 설정합니다. 이 설정이 올바로 되어있는지 확인하기 위해서는 블록 코드가 "040904e4"로 설정되어 있는지 확인하면 됩니다.

FireFox가 플러그인을 인식하도록 하기 위해서는 MIME 타입을 반드시 버전 정보에 포함시켜야 하는데, 이는 NPTest.rc 파일을 직접 수정하는 과정을 거쳐야 합니다.

NPTest.rc 예제
BLOCK "040904e4"
       BEGIN
           VALUE "Comments", "\0"
           VALUE "CompanyName", "ASP\0"
           VALUE "FileDescription", "NPTest\0"
           VALUE "FileExtents", "tst\0"
           VALUE "FileVersion", "1, 0, 0, 1\0"
           VALUE "InternalName", "NPTest\0"
           VALUE "LegalCopyright", "Copyright ⓒ 2006\0"
           VALUE "LegalTrademarks", "\0"
           VALUE "MIMEType", "application/test-plugin\0"
           VALUE "OriginalFilename", "NPTest.dll\0"
           VALUE "PrivateBuild", "\0"
           VALUE "ProductName", "ASP NPTest\0"
           VALUE "ProductVersion", "1, 0, 0, 1\0"
           VALUE "SpecialBuild", "\0"
       END

Step 8) 플러그인을 로드하는 HTML 작성

<embed> 태그를 이용해서 플러그인을 로드 할 수 있습니다. 위 예제에서는 type 속성을 명시해줌으로써 플러그인을 로드 할 수 있습니다.

Test.html 예제
<html>
<body>

<center><h1>Basic Plugin Example for Mozilla Test Case</h1></center>

This test case is to demonstrate the Basic Plugin example. You should see the
plugin window with the black frame aroung it and the browser user agent string
which plugin draws inside the window.
<br><br>

<center>
<embed type="application/test-plugin" width=600 height=40>
</center>

</html>
</body>
Embed 태그의 type 속성을 버전에서 정해준 MIME 타입으로 설정해둔 것을 볼 수 있습니다. 위의 HTML 파일을 FireFox로 불러오면 플러그인이 로드된다. 테스트를 위해서 플러그인 로드시 MessageBox를 띄우는 코드를 작성한 후 테스트 합니다.

Step 9) FireFox에서 불러오기

NPTest.cpp 수정 부분
NPError OSCALL NP_Initialize(NPNetscapeFuncs* aNPNFuncs)

AfxMessageBox( "hi" ) ;
return NPERR_NO_ERROR;
}

NP_Initialize에 AfxMessageBox를 불러오는 코드를 작성해봅니다. MFC를 사용하기 위해서는 프로젝트 설정 정보에서 Using MFC로 설정해야 하며, 다음과 같은 헤더 정보를 포함해야 합니다.

MFC를 사용하기 위한 헤더 설정
#include <afxwin.h>         // MFC 핵심 및 표준 구성 요소
#include <afxext.h>         // MFC 익스텐션
#include <afxdisp.h>        // MFC 자동화 클래스

이제 컴파일 한 후 결과 파일인 NPTest.dll 파일을 파이어폭스가 설치된 폴더에서 plugin 폴더에 복사한 후 위에서 작성한 test.html 파일을 불러오세요.

그림 1 Hi?

PlugIn이 실행되는걸 직접 확인하셨나요?

맨땅에서부터 정말로 실행되는 단계까지 직접 해보신 기분이 어떤가요? 플러그인 만드는 거 별거 아닌 것 같습니다. 여기에 자신의 아이디어를 적용시켜보세요!


본 글의 출처는 다음과 같습니다.

작성자 : 이은규
홈페이지 : http://unkyulee.net
작성일 : 2006-02-20
블로그 이미지

맨오브파워

한계를 뛰어 넘어서..........

,