- Write the shared code in a lightweight scripting language, and run a VM in C# and Java. Lua is one of this type.
- Write the shared code in a language than can translate both to C# and java, such as Haxe.
- Write the shared code in Java and use tools to translate to C#.
Sometimes, we already has some existing code in Java, so we are only left with the third option. Besides, even if there is no existing code, Java to C# is an attractive option thanks to Java's rich & friendly development environment.
Recently, I have to share some common logic between Java and C# . To be more specific, there is a Java based game server which are connected by an existing Flash client, what we want to do is to add another Unity client while preserving both Java and AS3's logic. After a lot of discussion, we decided to adopt the following strategy:
- First, refactor and extract the shared logic in the Java server to a standalone module which shouldn't be depend on any other java library except Java's buildin library.
- Second, translated the extracted module from java to C# use a tool such as sharpen.
We choose sharpen as our translating tool, because:
- first of all, it's open source and can be modified if necessary
- then, there are some successful application of it already, such as ngit.
There are lots of sharpen version on the internet, and I used the mono version with some multi dimension array fixed from anders9ustafsson's version, and pushed final result to my folk.
The document is very hard to find, so I made a backup in sharpen-doc.
Here are some other resources I found usefull:
- Build help: https://github.com/mono/sharpen
- Example configuration: https://github.com/ydanila/sharpen_imazen_config
- Sharpen C# utility classes: https://github.com/mono/ngit/tree/master/Sharpen/Sharpen
- Another sharpen blog: http://pauldb-blog.tumblr.com/post/14916717048/a-guide-to-sharpen-a-great-tool-for-converting
When running sharpen,do set -Dfile.encoding=UTF-8 option, or some file won't compile successfully.
Command line Arguments:
| Argument | Usage |
| -pascalCase | Convert Java identifiers to Pascal case |
| -pascalCase+ | Convert Java indentifiers and package names (namespaces) to Pascal case |
| -cp | Adds a new entry to classpath: |
| -srcFolder | Adds a new source folder for sharpening |
| -nativeTypeSystem | Map java classes to .NET classes with a similar functionality. For example: java.lang.Class - System.Type |
| -nativeInterfaces | Adds an "I" in front of the interface name |
| -organizeUsings | Adds "using" for the types used |
| -fullyQualify | Converts to a fully-qualified name: -fullyQualify File |
| -namespaceMapping | Maps a java package name to a .NET namespace. For example: -namespaceMapping com.db4o Db4objects.Db4o |
| -methodMapping | Maps a java method name to a .NET method (can be method in another class). For example: -methodMapping java.util.Date.getTime Sharpen.Runtime.ToJavaMilliseconds |
| -typeMapping | Maps a java class to .NET type: -typeMapping com.db4o.Db4o Db4objects.Db4o.Db4oFactory |
| -propertyMapping | Maps a java method to .NET property: -propertyMapping com.db4odoc.structured.Car.getPilot Pilot |
| -runtimeTypeName | Name of the runtime class. The runtime class provides implementation for methods that don't have a direct mapping or that are simpler to map at the language level than at the sharpen level. For instance: String.substring, String.valueOf, Exception.printStackTrace, etc. For a complete list of all the method that can be mapped to the runtime class see Configuration#runtimeMethod call hierarchy. |
| -header | Header comment to be added to all converted files. -header config/copyright_comment.txt |
| -xmldoc | Specifies an xml-overlay file, which overrides javadoc documentation for specific classes: -xmldoc config/sharpen/ApiOverlay.xml |
| -eventMapping | Converts the methods to an event. |
| -eventAddMapping | Marks the method as an event subscription method. Invocations to the method in the form |
| -conditionalCompilation |
Add a condition when to translate the Java code
- -conditionalCompilation com.db4o.db4ounit.common.cs !SILVERLIGHT
|
| -configurationClass | Change the configuration class. The default is 'sharpen.core.DefaultConfiguration' |
Annotation Reference:
| Annotation | Meaning |
| @sharpen.enum | Mark java class to be processed as a .NET enum |
| @sharpen.rename | Specifies a different name for the converted type, takes a single name argument. For example: @sharpen.rename Db4oFactory |
| @sharpen.private | Specifies that the element must be declared private in the converted file, though it can be not private in the java source:/* * @sharpen.private */public List4 _first; |
| @sharpen.internal | Specifies that the element must be declared internal in the converted file:/** * @sharpen.internal */public abstract int size(); |
| @sharpen.protected | Specifies that the element must be declared protected in the converted file:/** * @sharpen.protected */public abstract int size(); |
| @sharpen.new | Adds the C#-'new' modifier to the translated code. |
| @sharpen.event | Links an event to its arguments. For example: Java: /** * @sharpen.event com.db4o.events.QueryEventArgs */ public Event4 queryStarted();is converted to: public delegate void QueryEventHandler( object sender, Db4objects.Db4o.Events.QueryEventArgs args); ....... event Db4objects.Db4o.Events.QueryEventHandler QueryStarted; |
| @sharpen.event.add | Marks the method as an event subscription method. Invocations to the method in the form |
| @sharpen.event.onAdd | Valid for event declaration only (SHARPEN_EVENT). Configures the method to be invoked whenever a new event handler is subscribed to the event. |
| @sharpen.if | Add #if @sharpen.if |
| @sharpen.property | Convert a java method as a property:/** * @sharpen.property */public abstract int size(); |
| @sharpen.indexer | Marks an element as an indexer property |
| @sharpen.ignore | Skip the element while converting |
| @sharpen.ignore.extends | Ignore the extends clause in Java class definition |
| @sharpen.ignore.implements | Ignore the implements clause in Java class definition |
| @sharpen.extends | Adds an extends clause to the converted class definition. For example: Java: /**
* @sharpen.extends System.Collections.IList
*/
public interface ObjectSet {...
converts topublic interface IObjectSet : System.Collections.IList |
| @sharpen.partial | Marks the converted class as partial |
| @sharpen.remove | Marks a method invocation that should be removed |
| @sharpen.remove.first |
Removes the first line of the method/constructor when converting to C#:
/**
* @sharpen.remove.first
*/
public void doSomething(){
System.out.println("Java");
NextMethod();
}
converts to:
public void DoSomething(){
NextMethod();
}
|
| @sharpen.struct | Marks class to be converted as c# struct |
| @sharpen.unwrap |
When a method is marked with this annotation
all method calls are removed. This is useful for removing conversion methods when their aren't required in C#. /*
* @sharpen.unwrap
*/
public Iterable toIterable(Object[] array){
return Arrays.asList(array);
}
public void doSomething(Object[] objs){
Iterable iterable = toIterable(objs);
// do something with the iterable
}
Is converted to:
public IEnumerable ToIterable(object[] array){
return Arrays.AsList(array);
}
public void doSomething(object[] objs){
Iterable iterable = objs;
// do something with the iterable
}
|
| @sharpen.attribute |
Adds an attribute to the converted code:
/*
* @sharpen.attribute TheAttribute
*/
public void doSomething(){}
Will be converted to:
[TheAttribute]
public void DoSomething(){}
|
| @sharpen.macro | Add a replace-pattern macro to your code. |

0 评论:
Post a Comment