얼마전 jar 파일을 pas 파일로 만들기 위해서 JAVA2OP를 이용한 적이 있다. 물론 이를 다시 hpp로 만들어서 사용하려고 하는것이 목적이었다. 이번에 문제가 된 것은 RAD STUDIO 초기에 JAVA2OP를 해 보았을 때는 별 문제가 없다가, 이번에 다시 하면서 안되어 다른 사람들에게 거짓말쟁이가 되어 버렸다는 것이다.


아무튼 JAVA2OP를 사용하기 위해선 JAVA2OP가 있는 폴더 상에 변환할 jar 파일이 있는 것이 편하다.(자세한 것은 링크 참조.) 그리고 다음과 같이 작성을 한다.


java2op -jar android.jar -unit android 


물론 간단하게 java2op -jar android.jar 만 하여도 상관 없다. 저렇게 -unit XXX를 하면 원하는 이름으로 pas를 만들수 있다.(자세한 것은 링크 참조.)



본래대로면 정상적으로 완료를 했어야 했다. 그러나 이 녀석이 다음과 같은 에러를 내 뿜는다.


class or interface expected




그래서 인터넷을 검색해 보았다. 역시나 별 도움은 안된다. 저 애러는 일반적으로 class가 없을 때 나타나는 것이라고 하지만, 보통은 블록 { , } 가 완전하지 않을 때 발생하는 문제라고 한다.

하지만 내가 jar로 export 시킨 package는 컴파일 애러 없이 정상적으로 폰에서 돌아가고 있는 어플리케이션이었다. 결국 저 문제는 아니라는 이야기.


그래서 명령을 잘 못 친줄 알고 몇번을 반복해 보았는데, 그랬더니 가끔 변환이 되긴 한다. 하지만 그 결과는 실망스러웠다. 그냥 텅빈 파일이 생성된 것이었다.


{*******************************************************}

{                                                       }

{           CodeGear Delphi Runtime Library             }

{ Copyright(c) 2014 Embarcadero Technologies, Inc.      }

{                                                       }

{*******************************************************}


unit Androidapi.JNI.Interfaces;


interface


uses

  Androidapi.JNIBridge;


type

// ===== Forward declarations =====



// ===== Interface declarations =====


implementation


procedure RegisterTypes;

begin

end;


initialization

  RegisterTypes;

end.



그래서 권한 문제인 줄 알고 명령프롬프트창을 관리자 권한으로 열었는데도 동일해서, 무엇일까 한참을 고민을 했다.




그런데,




우연히 c:\~~~> 이 눈에 들어왔다. 거기서 눈에 띈것은 다름아님 한글주소... 펌웨어 짜던 시절 많이 당했던 함정 중 하나였던 한글 주소가 눈에 보였다. 그리고 혹시나 하는 마음에 해당 작업 디렉토리를 한글이 없는 곳으로 옮겼다.


그랬더니 그냥 아주 훌륭하게 pas 파일이 만들어 졌다. 아~ 내 아까운 시간... ㅠㅠ



결국 해당 애러는 작업 프로그램이 중간에 한글주소가 존재하여 발생하였던 문제였다.

Posted by klisty
,

안드로이드에선 Activity라는 것이 있다. 그와 대응하는 것이 바로 Firemonkey에선 Form이다.

그리고 최근(이라고 하지만 2년전이었나. 3년 전이었나?)에 안드로이드에선 Fragment라는 것이 도입되었다.

이것의 대응은 Firemonkey에선 MultiView와 Frame이다.


아무튼 어플리케이션을 만들다 보면 Form은 하나로 놓고, Frame을 다수로 만들어 Module화를 시도하는 경우가 있는데, 이러면 Form을 여러개 만들 때와는 다른 현상이 생기게 된다.


Form으로 각 화면들을 구성하였다면 Form1->BringToFront(); 와 같은 형대로 Form위에 오버뷰 시키기 때문에 뒤로가기버튼(Back Key)을 누르면 이전 Form이 불려와서 문제없이 동작되게 된다. 하지만 Frame으로 만들게 되면 처음부터 떠 있던 것이 Form1밖에 없어서 뒤로가기를 하여도 어플리케이션이 이전 Frame으로 가는 것이 아니라 바로 종료가 되어 버린다.


결국 이를 해결하기 위해선 Frame이 불려온 순서를 기억 할 수 밖에 없고 이를 위해 List를 사용하여 각각의 포인터를 기억하도록 시켰다.




[ Form1.h ] 

__published: // IDE-managed Components

void __fastcall FormKeyUp(TObject *Sender, WORD &Key, System::WideChar &KeyChar,

 TShiftState Shift);   <- 이건 Form에서 Event를 추가 하면 된다.


private: // User declarations

// frame의 생성 순서 기억

TList  *FrameList;


public: // User declarations

// Frame 순서와 관련된 함수

void* __fastcall FrameListCurrent(void);

int    __fastcall FrameListAdd(TFrame *ptFrame);

bool  __fastcall FrameListDelete(void);




[ Form1.cpp ]

void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, System::WideChar &KeyChar,

 TShiftState Shift)

{

if( Key == vkHardwareBack ){

// key값 초기화

Key = 0;


ButtonMainPrevClick(Sender);  <-- 이건 구지 이렇게 할 필요 없다.

}

}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

void __fastcall TForm1::ButtonMainPrevClick(TObject *Sender)

{

if( Form1->FrameListCurrent() ==  Frame1 ){

struct TCloseDialogHandler : public TCppInterfacedObject<TInputCloseDialogProc> {

void __fastcall Invoke(const System::Uitypes::TModalResult AResult) {

switch (AResult) {

case mrYes :

 Form1->Close();

break;

case mrNo:

return;

break;

}

}

};

_di_TInputCloseDialogProc HandlerMessageDlgExit = new TCloseDialogHandler();


MessageDlg("Do you want to exit? really?",

  TMsgDlgType::mtCustom,

  TMsgDlgButtons() << TMsgDlgBtn::mbNo << TMsgDlgBtn::mbYes , 0, HandlerMessageDlgExit);

}

else{

Form1->FrameListDelete();

}

}

//---------------------------------------------------------------------------

//---------------------------------------------------------------------------


int __fastcall TForm1::FrameListAdd(TFrame *ptFrame)

{

FrameList->Add(ptFrame);

return 0;

}

//---------------------------------------------------------------------------


bool __fastcall TForm1::FrameListDelete(void)

{

((TFrame*)FrameList->Last())->Parent = NULL;

((TFrame*)FrameList->Last())->Visible = false;


FrameList->Delete( FrameList->Count - 1 );


((TFrame*)FrameList->Last())->BringToFront();


return True;

}

//---------------------------------------------------------------------------


void* __fastcall TForm1::FrameListCurrent(void)

{

return FrameList->Last();

}

//---------------------------------------------------------------------------






Posted by klisty
,

RAD Studio EX7에서 코딩을 하다보면 자동완성 기능(컨트롤+스페이스) 안될 때가 있다.

(자동완성 기능을 다른 말로 뭐라 하던데 뭐라 하는지 모르겠다.)


문제는 자동완성 기능이 안되면 go to ~~~ (알트+방향키위)도 안된 다는 것;;;;



아무튼 ' :: ' , ' . ', ' -> '  이 3개 모두 안되는 경우가 있는데...



이 경우 Target Platforms 이 Android - Android SDK ~~ 으로 되어 있는지 확인할 필요가 있다.


Target Platform을 32-bit Windows 으로 변경하면 잘된다.

(64-bit Windows, iOS Device, OS X 모두 잘된다;;)



아무래도 RAD Studio EX7 자체의 버그인 듯............?!





추가 내용 : 위 내용은 잘 못된 내용으로 판단된다. 물론 임시적으로 해결은 가능하지만 완전한 해결 방법이 아닌것으로 파악되어 추가로 작성한다.


최근에 다시 비슷한 문제가 발생하여 다시 해결해 보려고 하였으나 잘 안되어 다음과 같이 질문들을 남겼다.

http://tech.devgear.co.kr/delphi_qna/409721


그 결과 다음과 같은 답변을 받고 델마당으로 가서 해법 대로 하였다.

https://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=0&indx=418682&page=18


말인즉슨, ctrl+space로 한영변환을 하는 키보드의 경우 발생할 수 있는 문제라고 한다.

그래서 R alt 키로 변경해 주거나, shift+space로 변경해야 한다는데,

해당 문제는 reg를 건드리거나 키보드 장치 인식을 변경 시키면 된다.


본인의 키보드의 경우 101키보드(씽크패드 키보드;;;)를 사용하다 보니 회사내에서 혼자만 발생한 문제라 해결을 못했는데, 일단은 지금은 되니 다행인 듯 하다.



다양한 한영변환 reg 변경 방법

http://www.kbdmania.net/xe/index.php?mid=tipandtech&search_target=title&search_keyword=%EB%A0%88%EC%A7%80&document_srl=1157342


Posted by klisty
,

RadStudio의 FireMonkey를 사용하여 안드로이드 어플리케이션을 개발하려고 학습 중에 Delphi 예제("나의 도서관 앱" 개발 따라하기 - (1) 사용자화면 만들기와 기능 구현하기)를 C++ Builder로 옴기는 뻘짓을 하는 중에 발생할 애러이다.




발생 애러

[bcc32 Error] MainForm.cpp(172): E2336 Pointer to overloaded function 'TRectF::TopLeft' doesn't match 'const TPointF &'

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(172): E2064 Cannot initialize 'const TPointF &' with 'undefined'

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(172): E2342 Type mismatch in parameter 'Point' (wanted 'const TPointF &', got 'void')

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(172): E2235 Member function must be called or its address taken

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(173): E2336 Pointer to overloaded function 'TRectF::BottomRight' doesn't match 'const TPointF &'

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(173): E2064 Cannot initialize 'const TPointF &' with 'undefined'

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(173): E2342 Type mismatch in parameter 'Point' (wanted 'const TPointF &', got 'void')

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)

[bcc32 Error] MainForm.cpp(173): E2235 Member function must be called or its address taken

  Full parser context

    MainForm.cpp(166): parsing: void _fastcall TForm1::FormVirtualKeyboardShown(TObject *,bool,const TRect &)




원본 소스 (Delphi)

procedure TForm1.FormVirtualKeyboardShown(Sender: TObject;

  KeyboardVisible: Boolean; const Bounds: TRect);

begin

  FKBBounds := TRectF.Create(Bounds);

  FKBBounds.TopLeft := ScreenToClient(FKBBounds.TopLeft);

  FKBBounds.BottomRight := ScreenToClient(FKBBounds.BottomRight);

  UpdateKBBounds;

end;




애러 발생 지점 (C++ Builder)

void __fastcall TForm1::FormVirtualKeyboardShown(TObject *Sender, bool KeyboardVisible,

  const TRect &Bounds)

{

    FKBBounds = (TRectF*)&Bounds;

    FKBBounds->TopLeft =  ScreenToClient( FKBBounds->TopLeft );

    FKBBounds->BottomRight =  ScreenToClient( FKBBounds->BottomRight );


    UpdateKBBounds();

}




문제 해결 (C++ Builder)

void __fastcall TForm1::FormVirtualKeyboardShown(TObject *Sender, bool KeyboardVisible,

  const TRect &Bounds)

{

    FKBBounds = (TRectF*)&Bounds;


    FKBBounds->TopLeft() =  ScreenToClient( FKBBounds->TopLeft() );

    FKBBounds->BottomRight() =  ScreenToClient( FKBBounds->BottomRight() );


    UpdateKBBounds();

}




개인적인 정리

그동안 함수포인터를 잘 사용해보지 않았던 관계로 잘못 옴겨서 발생한 error 같다. 우선 ScreenToClient를 살펴보면 http://docwiki.embarcadero.com/Libraries/XE7/en/FMX.Forms.TCommonCustomForm.ScreenToClient 에서 알수 있듯이 parameter 자체가 주소 참조, 반환은 value로 하는 것을 알 수 있다. 일단 그동안 함수의 주소를 넘기기 위해선 func 로 해야 하는 줄 알았기 때문에(실제로 C에선 parameter 부분( "()" )을 안 붙인다. 참고) "FKBBounds.TopLeft"로 작성을 하였으나, TopLeft() 자체가 TPointF의 포인터 반환이다보니 함수 자체의 완전체인 ()를 붙여야 했다.(그런데 그동안 알고 있기론 포인터 반환이어도 parameter는 생각 가능한 것으로 알고 있었다.) 그리고 함수 자체의 반환이 포인터이다 보니 이를 넘겨 받을 때도 동일하게 parameter 를 명시해 줬다.




참고 사이트

http://blog.hjf.pe.kr/255

http://docwiki.embarcadero.com/Libraries/XE7/en/Main_Page

http://shinluckyarchive.tistory.com/206




Posted by klisty
,

RadStudio의 FireMonkey를 사용하여 안드로이드 어플리케이션을 개발하려고 학습 중에 Delphi 예제("나의 도서관 앱" 개발 따라하기 - (1) 사용자화면 만들기와 기능 구현하기)를 C++ Builder로 옴기는 뻘짓을 하는 중에 발생할 애러이다.


발생 애러

[bcc32 Error] MainForm.cpp(135): E2034 Cannot convert 'TControl' to 'TControl *'

  Full parser context

    MainForm.cpp(127): parsing: void TForm1::UpdateKBBounds()




원본 소스 (Delphi)

procedure TForm1.UpdateKBBounds;

var

  LFocused : TControl;

  LFocusRect: TRectF;

begin

  FNeedOffset := False;

  if Assigned(Focused) then

  begin

    LFocused := TControl(Focused.GetObject);

 

    LFocusRect := LFocused.AbsoluteRect;

    LFocusRect.Offset(vsbEditFocus.ViewportPosition);

    if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and

       (LFocusRect.Bottom > FKBBounds.Top) then

    begin

      FNeedOffset := True;

      lytContentsNew.Align := TAlignLayout.Horizontal;

      vsbEditFocus.RealignContent;

      Application.ProcessMessages;

      vsbEditFocus.ViewportPosition := PointF(vsbEditFocus.ViewportPosition.X,

                                              LFocusRect.Bottom - FKBBounds.Top);

    end;

  end;

  if not FNeedOffset then

    RestorePosition;

end;


애러 발생 지점 (C++ Builder)

void TForm1::UpdateKBBounds(void)

{

TControl *LFocused;

TRectF   LFocusRect;


FNeedOffset = false;


if( Focused )

{

LFocused = TControl( Focused->GetObject() );


LFocusRect = LFocused->AbsoluteRect;

LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );


if(  ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )

  && ( LFocusRect.Bottom > FKBBounds->Top ) )

{

FNeedOffset = true;

lytContentsNew->Align = TAlignLayout::Horizontal;

vsbEditFocus->RealignContent();

Application->ProcessMessages();

vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,

 LFocusRect.Bottom - FKBBounds->Top );

}

}

else if( FNeedOffset )

{

RestorePosition();

}

}




문제 해결 (C++ Builder)

void TForm1::UpdateKBBounds(void)

{

TControl *LFocused;

TRectF   LFocusRect;


FNeedOffset = false;


if( Focused )

{

LFocused = (TControl*)(IControl*)Focused;

                //LFocused = (TControl*)(Focused->GetObject());


LFocusRect = LFocused->AbsoluteRect;

LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );


if(  ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )

  && ( LFocusRect.Bottom > FKBBounds->Top ) )

{

FNeedOffset = true;

lytContentsNew->Align = TAlignLayout::Horizontal;

vsbEditFocus->RealignContent();

Application->ProcessMessages();

vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,

                                                            LFocusRect.Bottom - FKBBounds->Top );

}

}

else if( FNeedOffset )

{

RestorePosition();

}

}




개인적인 정리

처음엔 TControl로 convert 할 수 있는 TControl()도 존재하고, Focused가 속한 class인 TCommonCustomForm에 GetObject() 메소드가 있으므로 별 문제 없어 보였으나 막상 컴파일 하니 Convert를 못한다고 하였다. 그래서 "LFocused = (TControl*)(IControl*)Focused;" 하여 포인터를 넘길 때 TControl의 포인터로 강제 형 변환시켰다. 문제는 이게 소뒷걸음치다 잡은 문제라는 것이고, 사실 다른 더 좋은 방법이 있었다는 것이다. 아무튼 해결한 방법은 Focused에서 ->의 지시자를 하면 선택 가능한 메소드?들이 검색되질 않는다. 그래서 여기서부터 뻘짓을 시작하였다. Focused를 일종의 배열 같은 것으로 판단하였고, 하위에 메소드같은 것을 받은 것이 없으므로 검색되지 않는다고 생각했다. 그래서 Focused 자체를 가지고 Object를 알아 내는 방법을 찾았는데. 일단 TControl로 안된다고 하여 "LFocused = (TControl*)&Focused;"로 포인터를 강제형변환 시키도록 수정하였다. 그런데 문제는 이게 컴파일은 통과를 했는데 런타임에러가 발생했다. 

여기서부터 어떻게 해결해야 할지 몰라서 정신줄 놓고 검색을 계속하다 이것이 Delphi에서 변환된 녀석이고 따라서 IControld의 형태로 변환된 녀석임을 알게 되어서  "LFocused = (TControl*)(IControl*)Focused;" 이렇게 변환을 2번 하는 코드를 만들게 되었다. 그 결과 제대로 되었는데....................

지금 막 이 정리를 하면서 "LFocused = (TControl*)(Focused->GetObject());"로 소스를 넣고 컴파일 하니 컴파일도 되고 제대로 동작을 한다;;;  여기서 의문인것은 왜 "Focused->"하면 메소드나 변수을 선택하는 팝업이 안 뜨냐는 것인데, C++도 잘 못할 뿐더러 RadStudio를 처음 쓰기에 잘 모르겠다. 이거은 차근히 풀어 나가야 할듯 하다. 



참고 사이트

http://blog.hjf.pe.kr/255



Posted by klisty
,

RadStudio의 FireMonkey를 사용하여 안드로이드 어플리케이션을 개발하려고 학습 중에 Delphi 예제("나의 도서관 앱" 개발 따라하기 - (1) 사용자화면 만들기와 기능 구현하기)를 C++ Builder로 옴기는 뻘짓을 하는 중에 발생할 애러이다.


발생 애러

[bcc32 Error] MainForm.cpp(134): E2268 Call to undefined function 'Assigned'

  Full parser context

    MainForm.cpp(127): parsing: void TForm1::UpdateKBBounds()




원본 소스 (Delphi)

procedure TForm1.UpdateKBBounds;

var

  LFocused : TControl;

  LFocusRect: TRectF;

begin

  FNeedOffset := False;

  if Assigned(Focused) then

  begin

    LFocused := TControl(Focused.GetObject);

 

    LFocusRect := LFocused.AbsoluteRect;

    LFocusRect.Offset(vsbEditFocus.ViewportPosition);

    if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and

       (LFocusRect.Bottom > FKBBounds.Top) then

    begin

      FNeedOffset := True;

      lytContentsNew.Align := TAlignLayout.Horizontal;

      vsbEditFocus.RealignContent;

      Application.ProcessMessages;

      vsbEditFocus.ViewportPosition := PointF(vsbEditFocus.ViewportPosition.X,

                                              LFocusRect.Bottom - FKBBounds.Top);

    end;

  end;

  if not FNeedOffset then

    RestorePosition;

end;


애러 발생 지점 (C++ Builder)

void TForm1::UpdateKBBounds(void)

{

TControl *LFocused;

TRectF   LFocusRect;


FNeedOffset = false;


if( Assigned(Focused) )

{

LFocused = (TControl*)(IControl*)Focused;


LFocusRect = LFocused->AbsoluteRect;

LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );


if(  ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )

 && ( LFocusRect.Bottom > FKBBounds->Top ) )

{

FNeedOffset = true;

lytContentsNew->Align = TAlignLayout::Horizontal;

vsbEditFocus->RealignContent();

Application->ProcessMessages();

vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,

LFocusRect.Bottom - FKBBounds->Top );

}

}

else if( FNeedOffset )

{

RestorePosition();

}

}




문제 해결 (C++ Builder)

void TForm1::UpdateKBBounds(void)

{

TControl *LFocused;

TRectF   LFocusRect;


FNeedOffset = false;


if( Focused )

{

LFocused = (TControl*)(IControl*)Focused;


LFocusRect = LFocused->AbsoluteRect;

LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );


if(  ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )

  && ( LFocusRect.Bottom > FKBBounds->Top ) )

{

FNeedOffset = true;

lytContentsNew->Align = TAlignLayout::Horizontal;

vsbEditFocus->RealignContent();

Application->ProcessMessages();

vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,

                                                            LFocusRect.Bottom - FKBBounds->Top );

}

}

else if( FNeedOffset )

{

RestorePosition();

}

}




개인적인 정리

Assigned 자체는 http://docwiki.embarcadero.com/Libraries/XE7/en/System.Assigned 를 읽어보면, Delphi에서만 지원하기 때문에 undefined function 이 발생하는 것으로 보인다. 그리고 하단의 설명을 더 읽어 보면 "function Assigned(var P): Boolean;", "Tests for a nil (unassigned) pointer or procedural variable."라는 문장을 봐선 결국 var P이 제대로 할당되어 있는지를 파악하는 것으로 판단했다. 따라서 Focused가 제대로 할당 되었는지만 보면 되기 때문에 Assigned를 지우고 Focused의 주소값을 바로 비교 할 수 있도록 하였다.



참고 사이트

http://blog.hjf.pe.kr/255



Posted by klisty
,