Added ikvm.lang.DllExport annotation to export static methods as unmanaged exports.

This commit is contained in:
jfrijters 2011-11-11 15:35:13 +00:00
Родитель ad824ad22e
Коммит 0f0a0963c7
5 изменённых файлов: 128 добавлений и 8 удалений

Просмотреть файл

@ -0,0 +1,40 @@
/*
Copyright (C) 2011 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package ikvm.lang;
import java.lang.annotation.*;
/**
* Can be used to define an unmanaged export for a static method.
* Only works with ikvmc compiled code.
*/
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.METHOD })
public @interface DllExport
{
String name();
int ordinal();
}

Просмотреть файл

@ -3276,6 +3276,11 @@ namespace IKVM.Internal
{
StaticCompiler.IssueMessage(options, msgId, values);
}
internal void ClearILOnlyFlag()
{
options.pekind &= ~PortableExecutableKinds.ILOnly;
}
}
struct ResourceItem
@ -3403,6 +3408,7 @@ namespace IKVM.Internal
LegacySearchRule = 126,
AssemblyLocationIgnored = 127,
InterfaceMethodCantBeInternal = 128,
DllExportMustBeStaticMethod = 129,
UnknownWarning = 999,
// This is where the errors start
StartErrors = 4000,
@ -3621,6 +3627,10 @@ namespace IKVM.Internal
msg = "ignoring @ikvm.lang.Internal annotation on interface method" + Environment.NewLine +
" (\"{0}.{1}{2}\")";
break;
case Message.DllExportMustBeStaticMethod:
msg = "ignoring @ikvm.lang.DllExport annotation on non-static method" + Environment.NewLine +
" (\"{0}.{1}{2}\")";
break;
case Message.UnableToCreateProxy:
msg = "unable to create proxy \"{0}\"" + Environment.NewLine +
" (\"{1}\")";

Просмотреть файл

@ -12,6 +12,7 @@
../classpath/ikvm/internal/WeakIdentityMap.java
../classpath/ikvm/io/InputStreamWrapper.java
../classpath/ikvm/lang/CIL.java
../classpath/ikvm/lang/DllExport.java
../classpath/ikvm/lang/Internal.java
../classpath/ikvm/lang/IterableEnumerator.java
../classpath/ikvm/lang/MapEnumerator.java

Просмотреть файл

@ -2448,8 +2448,15 @@ namespace IKVM.Internal
{
private Code code;
private string[] exceptions;
private object annotationDefault;
private object[][] parameterAnnotations;
private LowFreqData low;
sealed class LowFreqData
{
internal object annotationDefault;
internal object[][] parameterAnnotations;
internal string DllExportName;
internal int DllExportOrdinal;
}
internal Method(ClassFile classFile, ClassFileParseOptions options, BigEndianBinaryReader br) : base(classFile, br)
{
@ -2541,16 +2548,20 @@ namespace IKVM.Internal
{
goto default;
}
if(low == null)
{
low = new LowFreqData();
}
BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
byte num_parameters = rdr.ReadByte();
parameterAnnotations = new object[num_parameters][];
low.parameterAnnotations = new object[num_parameters][];
for(int j = 0; j < num_parameters; j++)
{
ushort num_annotations = rdr.ReadUInt16();
parameterAnnotations[j] = new object[num_annotations];
low.parameterAnnotations[j] = new object[num_annotations];
for(int k = 0; k < num_annotations; k++)
{
parameterAnnotations[j][k] = ReadAnnotation(rdr, classFile);
low.parameterAnnotations[j][k] = ReadAnnotation(rdr, classFile);
}
}
if(!rdr.IsAtEnd)
@ -2565,8 +2576,12 @@ namespace IKVM.Internal
{
goto default;
}
if(low == null)
{
low = new LowFreqData();
}
BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
annotationDefault = ReadAnnotationElementValue(rdr, classFile);
low.annotationDefault = ReadAnnotationElementValue(rdr, classFile);
if(!rdr.IsAtEnd)
{
throw new ClassFormatError("{0} (AnnotationDefault attribute has wrong length)", classFile.Name);
@ -2597,6 +2612,38 @@ namespace IKVM.Internal
{
flags |= FLAG_HAS_CALLERID;
}
if(annot[1].Equals("Likvm/lang/DllExport;"))
{
string name = null;
int? ordinal = null;
for (int j = 2; j < annot.Length; j += 2)
{
if (annot[j].Equals("name") && annot[j + 1] is string)
{
name = (string)annot[j + 1];
}
else if (annot[j].Equals("ordinal") && annot[j + 1] is int)
{
ordinal = (int)annot[j + 1];
}
}
if (name != null && ordinal != null)
{
if (!IsStatic)
{
StaticCompiler.IssueMessage(Message.DllExportMustBeStaticMethod, classFile.Name, this.Name, this.Signature);
}
else
{
if (low == null)
{
low = new LowFreqData();
}
low.DllExportName = name;
low.DllExportOrdinal = ordinal.Value;
}
}
}
}
break;
#endif
@ -2672,7 +2719,7 @@ namespace IKVM.Internal
{
get
{
return parameterAnnotations;
return low == null ? null : low.parameterAnnotations;
}
}
@ -2680,7 +2727,23 @@ namespace IKVM.Internal
{
get
{
return annotationDefault;
return low == null ? null : low.annotationDefault;
}
}
internal string DllExportName
{
get
{
return low == null ? null : low.DllExportName;
}
}
internal int DllExportOrdinal
{
get
{
return low == null ? -1 : low.DllExportOrdinal;
}
}

Просмотреть файл

@ -4342,6 +4342,12 @@ namespace IKVM.Internal
AttributeHelper.SetEditorBrowsableNever((MethodBuilder)mb);
EmitCallerIDStub(methods[i], parameterNames);
}
if (m.DllExportName != null)
{
mBuilder.__AddUnmanagedExport(m.DllExportName, m.DllExportOrdinal);
// when you add unmanaged exports, the ILOnly flag MUST NOT be set or the DLL will fail to load
((CompilerClassLoader)wrapper.GetClassLoader()).ClearILOnlyFlag();
}
#endif // STATIC_COMPILER
}