C# AST Parser


Abstract Syntax Tree

한마디로 언어에 관계 없는 프로그래밍 언어의 형태를 나타내어 주는 간략한 트리라고 볼 수 있다.

위키


종류

-Cecil : C#의 IL코드를 분석하여 컴파일?하는 방식

-NRefactory : Cecil 오픈 라이브러리를 이용하여 AST 파서를 만들어 제공하는 것으로 요즘 내가 사용하고 있는 오픈소스 라이브러리임.


NRefactory

Github에서 소스파일이나 Library(Dll) 파일을 받을 수 있으며 사용하는 방법은 CodeProject의 예제에 나와있다. (NRefactory_Demo_and_IndexOf-Sample_-_Source)

Method 들의 호출관계(Call Hierarchy)를 구하고 싶어서 사용했으며 예시 코드는 다음과 같다.


이 프로젝트를 진행하면서 고생했던 것은

1. 오픈소스 라이브러리의 존재 유무

오픈소스 라이브러리가 있는 줄 몰랐기 때문에 처음에는 갖은 방법을 생각했었다.

처음 생각했던 것은 직접 Parser를 구현했지만 역시나 컴파일러 수준으로 작성하는 것은 효율적이지 못했고 어려웠다.

두번째로 생각했던 것은 정규표현식으로 함수모양으로 생긴 것들을 찾아내는 것이었으나 주석안에 있는 함수 등등 상당한 문제를 내포하고 있었다 (주석을 지우고 실행하는 것으로 해결)

마지막으로 찾은 것이 바로 AST Parser였다.

2. 오픈소스 라이브러리의 사용 방법

라이브러리마다 다른 사용법을 가지고 작성되었기 때문에 각각의 특성에 맞게 이용하는 것이 중요하다. 하지만 어떤 구성으로 되어있는지 처음에 사용하기도 어려웠기 때문에 Demo를 통해서 분석했다.

메소드는 어떤 타입으로 검사해야되는지(IMethod, MethodDeclaration) 등등 원하는 정보를 찾는 것도 어려웠다.

3. Find References

호출관계를 구하는 과정에서 시간이 오래걸렸다. 초기의 버전에서는 Method의 Call Hierarchy를 구할때마다 재귀적인 방식으로 FindReferences를 이용하여 구했는데 (해당 주소로 이동) 매번 호출하게 되니 거의 3분가량의 시간이 소모되었다. 개선하는 과정에서 Call Hierarchy를 Map으로 저장해두고 필요할때 타고 이동하는 방식을 사용해야겠다고 생각되었다.

4. Hash Collision

Method를 Hashtable에 넣어서 Call Hierarchy를 저장해두는 방식을 택하게 되었는데 어떤 문제인지 모르겠지만 계속 Hash값이 충돌되는 일이 발생되었다. 처음에는 GetHashCode에 문제가 있는 것 같아서 새로운 Hash값을 넣었지만 같은 충돌이 계속발생되었다. 같은 Method를 2번씩 넣기에 .cs이 중복되지 않았으며 Method는 계속 2번씩 호출되고 있었다. 그 이유는 interface를 피하고 class만을 구하는 방법이 잘못된 것이었다. 해결하기 위해 Method의 BodyRegion이 비어있는지 확인하는 것으로 해결했다.

5. Interface

Class의 method만을 가져오려고하는데 계속 Interface까지 가져오기에 함수가 두번씩 나오게 되었다. 이를 처리하기 위해서 Class를 먼저 구하고, 그 class 내부에서 method를 찾는 방식으로 진행했는데 partial class에서 method를 2번씩 가져오는 문제가 발생되었다.


여러가지 삽질끝에 NRefactory Parser를 잘 쓸 수 있게 됐다.

'프로그래밍 > C#' 카테고리의 다른 글

[Unity] Android Plugin  (0) 2015.09.29
[Error] ClickOnce error  (0) 2014.11.21
FTP with .NET (C#)  (0) 2014.10.21
by 개발자가 되자! 2015. 11. 3. 15:01

필요한 것들

- 안드로이드 개발환경, 유니티

안드로이드 스튜디오(기준으로 설명) 혹은 안드로이드를 개발가능한 이클립스






- 안드로이드 스튜디오를 이용하여 프로젝트를 생성한다

blank로 하던 Add No Activity로 하던 안에 있는거 다 삭제

res 안에 것들


- .java 파일을 하나 만든다

package stars.com.starsplugin;

AndroidManager.cs


Plugin.java



import android.util.Log;
import com.unity3d.player.UnityPlayer;

public class Plugin {
private static Plugin _plugin = null;
private Plugin() {

}
public static Plugin getInstance() {
if (_plugin == null) {
_plugin = new Plugin();
}
return _plugin;
}

public void CallAndroid(String msg)
{
Log.d("MYTEST", "CallAndroid");
String message = msg + "(by CallAndroid)";
UnityPlayer.UnitySendMessage("AndroidManager", "SetLog", message);
}
}

이대로라면 import가 되지 않았다며 빨간줄이 뜰 것이므로


- classes.jar 설정

 C:\Program Files\Unity\Editor\Data\PlaybackEngines\androidplayer\development\bin\classes.jar

복사

C:\Users\Administrator\AndroidStudioProjects\project\app\libs


Open Module Settings -> Dependencies -> File dependency -> libs/classes.jar 추가







- Gradle 설정

Gradle Scripts -> build.gradle(Module:app) 열기

아래와 같이 수정


apply plugin: 'com.android.library' // application -> library

android {
compileSdkVersion 22
buildToolsVersion "22.0.1"

defaultConfig {
// applicationId "com."
minSdkVersion 15
targetSdkVersion 22
// versionCode 1
// versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile files('libs/classes.jar')
}

//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'release/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)

- Make Module App (Ctrl + Shift + F9) 를 실행한다


- 안드로이드 스튜디오의 오른쪽에 보면 Gradle Project가 있다.

Project -> :app -> Tasks -> other -> exportJar을 Run 한다.



- C:\Users\Administrator\AndroidStudioProjects\StarsPlugin\app\release 폴더에 가면

AndroidPlugin.jar 파일이 생긴다.

- UnityProject의 Assets\Plugins\Android 폴더로 옮긴다.




- 유니티 스크립트에서 


public void CallJavaFunc(string strFuncName, string strTemp)

{ using (AndroidJavaClass cls = new AndroidJavaClass("stars.com.starsplugin.Plugin")) {   using (AndroidJavaObject stars = cls.CallStatic<AndroidJavaObject>("getInstance"))

  {

    stars.Call(strFuncName, strTemp);

  }

} }

public void SetLog(string strJavaLog) { Debug.Log("message from java: " + strJavaLog); GameObject.Find("GameManager").GetComponent<debug>().strLog = strJavaLog; strLog = strJavaLog; }

- 유니티의 함수를 호출하기 위해 유니티에서 Empty Object를 생성하고




GameObject이름을 동일하게 해준다. UnityPlayer.UnitySendMessage("AndroidManager", "SetLog", message);

UnitySendMessage의 정의는 UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");



함수가 있는 스크립트를 추가해줌





잘나온다




- 끗

무슨 NativePlayer니 어쩌니 그딴거 쓸일이 뭐가있나 삽질..


첨부파일 참고


참고 사이트 : http://answers.unity3d.com/questions/437708/jni-exception-using-android-plugin.html

http://docs.unity3d.com/Manual/PluginsForAndroid.html

http://blog.naver.com/bluefallsky/220110061131

gradle 파일 참고 : http://egloos.zum.com/dra784/v/11168585


'프로그래밍 > C#' 카테고리의 다른 글

[C# Parser] NRefactory  (0) 2015.11.03
[Error] ClickOnce error  (0) 2014.11.21
FTP with .NET (C#)  (0) 2014.10.21
by 개발자가 되자! 2015. 9. 29. 20:37

Click Once를 통해 프로그램을 업데이트 했다.

프로젝트가 2010버전에서 Visual Studio 2013으로 바뀐 만큼 dll이 지원하는 버전이 달랐기에  .Net 4.0으로 업데이트를 해야만 했다.


ClickOnce로 Publish를 하고 잘돌아가는지 실행하는 순간


 Can not ... blah blah

  

 OK

 Detail



파일 서명이 일치하지 않아서 설치를 할 수 없다나..


Detail을 눌러보니


 Reference in the manifest does not match the identity of the downloaded assembly  ... .Interop.dll


여기저기 구글링해보아도 해결책이 없었다.


In project properties -> Application tab -> Resources -> checkbox Icon and manifest, the setting "Embed manifest with default settings" caused the problem. Setting it to "Create application without a manifest" fixes the problem.


Application의 Icon이 Embed manifest with default settings 때문에 문제가 발생한다는 글 뿐이었다.



문제를 해결한 방법은 이전에 사용하던 파일들 때문인 것 같았다.

Publish 폴더 전체를 날려버리고 다시 하니 성공!

'프로그래밍 > C#' 카테고리의 다른 글

[C# Parser] NRefactory  (0) 2015.11.03
[Unity] Android Plugin  (0) 2015.09.29
FTP with .NET (C#)  (0) 2014.10.21
by 개발자가 되자! 2014. 11. 21. 07:06

FTP

FTP는 보안이 이루어지지 않은 채로 통신이 이루어지는 옛 버전


SFTP

FTP에 Security가 포함되어있다는 뜻으로 3가지 정도의 의미를 갖고있다


1. SFTP (SSL File Transfer Protocol)

FTP와는 완전히 관계가 없는 파일 전송 프로토콜이다, SSL을 이용한다


2. SecureFTP (FTP/SSH)

SSH 연결 위에 일반 FTP로 접속을 하지만 실제 데이터는 암호화 되지 않는다


3. FTPS (or FTP/SSL) implicit & explicit

FTP가 TLS/SSL 보안 연결에서 동작한다. TLS(Transport Layer Security)/SSL(Secure Sockets Layer) 연결을 구성하는데에 따라 'implicit' 또는 'explicit'으로 구분이 된다.


TLS/SSL - Explicit mode

TLS/SSL - Implicit mode

Communication schema:

  1. Client connects to the server.
  2. Client explicitly requests TLS/SSL encryption to be switched on.
  3. Client talks to the server using encrypted channel.
  4. Username + password is sent encrypted.

Communication schema:

  1. Client connects to the server and TLS/SSL encryption is switched on implicitly as soon as the channel is established.
  2. Client talks to the server using encrypted channel.
  3. Username + password is sent encrypted.

ProtocolPlain port
(no encryption)
TLS/SSL Explicit portTLS/SSL Implicit port
FTP2121990
IMAP143143993
SMTP25 or 58725 or 587465
POP3110110995
HTTP80-443




.Net 지원 여부

API support
 
FTP - supported via FtpWebRequest included in .NET
FTPS - implicit - not support by .NET out of the box. You'll need a third party support. 

FTPS - explicit - supported in FtpWebRequest in .NET
SFTP - not support by .NET out of the box. You'll need a third party support.


출처 : http://www.codeproject.com/Questions/544479/C-plussftpplusdownloadplusandplusupload

http://doodoodoo.egloos.com/1377894

'프로그래밍 > C#' 카테고리의 다른 글

[C# Parser] NRefactory  (0) 2015.11.03
[Unity] Android Plugin  (0) 2015.09.29
[Error] ClickOnce error  (0) 2014.11.21
by 개발자가 되자! 2014. 10. 21. 05:08
| 1 |