Skip to content

Commit f79e0ef

Browse files
committed
Continue implementation of NAPI generator.
1 parent cd76498 commit f79e0ef

File tree

10 files changed

+486
-237
lines changed

10 files changed

+486
-237
lines changed

src/Generator/Generators/C/NAPI/NAPIGenerator.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ public NAPIGenerator(BindingContext context) : base(context)
1414
{
1515
}
1616

17+
public override bool SetupPasses()
18+
{
19+
var typeCheck = new NAPITypeCheck();
20+
Context.TranslationUnitPasses.AddPass(typeCheck);
21+
22+
return true;
23+
}
24+
1725
public override List<GeneratorOutput> Generate()
1826
{
1927
var outputs = base.Generate();

src/Generator/Generators/C/NAPI/NAPIHelpers.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ private void GenerateHelpers()
127127
WriteLine(@"#define NAPI_IS_UINT32(valuetype, value) (NAPI_IS_NUMBER(valuetype) && napi_is_uint32(env, value, nullptr))");
128128
WriteLine(@"#define NAPI_IS_INT64(valuetype, value) (NAPI_IS_BIGINT(valuetype))");
129129
WriteLine(@"#define NAPI_IS_UINT64(valuetype, value) (NAPI_IS_BIGINT(valuetype))");
130+
WriteLine(@"#define NAPI_IS_ARRAY(valuetype) (valuetype == napi_object)");
131+
WriteLine(@"#define NAPI_IS_OBJECT(valuetype) (valuetype == napi_object)");
132+
130133
NewLine();
131134
}
132135
}

src/Generator/Generators/C/NAPI/NAPIMarshal.cs

Lines changed: 70 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.Linq;
23
using CppSharp.AST;
34
using CppSharp.AST.Extensions;
45
using CppSharp.Generators.C;
6+
using CppSharp.Generators.Cpp;
57
using CppSharp.Types;
68
using Delegate = CppSharp.AST.Delegate;
79
using Type = CppSharp.AST.Type;
@@ -58,68 +60,10 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
5860
if (!VisitType(pointer, quals))
5961
return false;
6062

61-
var pointee = pointer.Pointee.Desugar();
62-
63-
PrimitiveType primitive;
64-
var param = Context.Parameter;
65-
if (param != null && (param.IsOut || param.IsInOut) &&
66-
pointee.IsPrimitiveType(out primitive))
67-
{
68-
Context.Return.Write(Context.ReturnVarName);
69-
return true;
70-
}
71-
72-
if (pointee.IsPrimitiveType(out primitive))
73-
{
74-
var returnVarName = Context.ReturnVarName;
75-
76-
if (pointer.GetFinalQualifiedPointee().Qualifiers.IsConst !=
77-
Context.ReturnType.Qualifiers.IsConst)
78-
{
79-
var nativeTypePrinter = new CppTypePrinter(Context.Context)
80-
{ PrintTypeQualifiers = false };
81-
var returnType = Context.ReturnType.Type.Desugar();
82-
var constlessPointer = new PointerType()
83-
{
84-
IsDependent = pointer.IsDependent,
85-
Modifier = pointer.Modifier,
86-
QualifiedPointee = new QualifiedType(returnType.GetPointee())
87-
};
88-
var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers());
89-
returnVarName = string.Format("const_cast<{0}>({1})",
90-
nativeConstlessTypeName, Context.ReturnVarName);
91-
}
92-
93-
if (pointer.Pointee is TypedefType)
94-
{
95-
var desugaredPointer = new PointerType()
96-
{
97-
IsDependent = pointer.IsDependent,
98-
Modifier = pointer.Modifier,
99-
QualifiedPointee = new QualifiedType(pointee)
100-
};
101-
var nativeTypePrinter = new CppTypePrinter(Context.Context);
102-
var nativeTypeName = desugaredPointer.Visit(nativeTypePrinter, quals);
103-
Context.Return.Write("reinterpret_cast<{0}>({1})", nativeTypeName,
104-
returnVarName);
105-
}
106-
else
107-
Context.Return.Write(returnVarName);
108-
109-
return true;
110-
}
63+
if (pointer.IsConstCharString())
64+
return VisitPrimitiveType(PrimitiveType.String);
11165

112-
TypeMap typeMap = null;
113-
Context.Context.TypeMaps.FindTypeMap(pointee, out typeMap);
114-
115-
Class @class;
116-
if (pointee.TryGetClass(out @class) && typeMap == null)
117-
{
118-
var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName
119-
: Context.ReturnVarName;
120-
WriteClassInstance(@class, instance);
121-
return true;
122-
}
66+
var pointee = pointer.Pointee.Desugar();
12367

12468
return pointer.QualifiedPointee.Visit(this);
12569
}
@@ -220,6 +164,10 @@ public bool VisitPrimitiveType(PrimitiveType primitive)
220164
return true;
221165

222166
case PrimitiveType.String:
167+
Context.Before.WriteLine($"napi_value {result};");
168+
Context.Before.WriteLine($"status = {func}(env, {Context.ReturnVarName}, NAPI_AUTO_LENGTH, &{result});");
169+
Context.Before.WriteLine("assert(status == napi_ok);");
170+
Context.Return.Write(result);
223171
return true;
224172

225173
case PrimitiveType.Null:
@@ -298,26 +246,31 @@ public override bool VisitClassDecl(Class @class)
298246
if (@class.CompleteDeclaration != null)
299247
return VisitClassDecl(@class.CompleteDeclaration as Class);
300248

301-
var instance = string.Empty;
302-
303-
if (Context.Context.Options.GeneratorKind == GeneratorKind.CLI)
304-
{
305-
if (!Context.ReturnType.Type.IsPointer())
306-
instance += "&";
307-
}
308-
309-
instance += Context.ReturnVarName;
310-
var needsCopy = Context.MarshalKind != MarshalKind.NativeField;
311-
312-
if (@class.IsRefType && needsCopy)
313-
{
314-
var name = Generator.GeneratedIdentifier(Context.ReturnVarName);
315-
Context.Before.WriteLine($"auto {name} = {MemoryAllocOperator} ::{{0}}({{1}});",
316-
@class.QualifiedOriginalName, Context.ReturnVarName);
317-
instance = name;
318-
}
249+
var ctor = @class.Constructors.FirstOrDefault();
250+
var ctorRef = $"ctor_{NAPISources.GetCIdentifier(Context.Context, ctor)}";
251+
var ctorId = $"__{Context.ReturnVarName}_ctor";
252+
Context.Before.WriteLine($"napi_value {ctorId};");
253+
Context.Before.WriteLine($"status = napi_get_reference_value(env, {ctorRef}, &{ctorId});");
254+
Context.Before.WriteLine("assert(status == napi_ok);");
255+
Context.Before.NewLine();
256+
257+
var instanceId = $"__{Context.ReturnVarName}_instance";
258+
Context.Before.WriteLine($"napi_value {instanceId};");
259+
Context.Before.WriteLine($"status = napi_new_instance(env, {ctorId}, 0, nullptr, &{instanceId});");
260+
Context.Before.WriteLine("assert(status == napi_ok);");
261+
Context.Before.NewLine();
262+
263+
/*
264+
var refId = $"__{Context.ReturnVarName}_ref";
265+
Context.Before.WriteLine($"napi_ref {refId};");
266+
267+
var dtorId = $"dtor_{NAPISources.GetCIdentifier(Context.Context, ctor)}";
268+
Context.Before.WriteLine($"status = napi_wrap(env, _this, {instanceId}, {dtorId}" +
269+
$", nullptr, &{refId});");
270+
Context.Before.WriteLine("assert(status == napi_ok);");
271+
*/
272+
Context.Return.Write($"{instanceId}");
319273

320-
WriteClassInstance(@class, instance);
321274
return true;
322275
}
323276

@@ -329,28 +282,6 @@ public string QualifiedIdentifier(Declaration decl)
329282
return decl.QualifiedName;
330283
}
331284

332-
public void WriteClassInstance(Class @class, string instance)
333-
{
334-
if (@class.CompleteDeclaration != null)
335-
{
336-
WriteClassInstance(@class.CompleteDeclaration as Class, instance);
337-
return;
338-
}
339-
340-
if (!Context.ReturnType.Type.Desugar().IsPointer())
341-
{
342-
Context.Return.Write($"{instance}");
343-
return;
344-
}
345-
346-
if (@class.IsRefType)
347-
Context.Return.Write($"({instance} == nullptr) ? nullptr : {MemoryAllocOperator} ");
348-
349-
Context.Return.Write($"{QualifiedIdentifier(@class)}(");
350-
Context.Return.Write($"(::{@class.QualifiedOriginalName}*)");
351-
Context.Return.Write($"{instance})");
352-
}
353-
354285
public override bool VisitFieldDecl(Field field)
355286
{
356287
return field.Type.Visit(this);
@@ -382,10 +313,8 @@ public override bool VisitTypedefDecl(TypedefDecl typedef)
382313

383314
public override bool VisitEnumDecl(Enumeration @enum)
384315
{
385-
var typePrinter = new CppTypePrinter(Context.Context);
386-
typePrinter.PushContext(TypePrinterContextKind.Managed);
387-
var typeName = typePrinter.VisitDeclaration(@enum);
388-
Context.Return.Write($"({typeName}){Context.ReturnVarName}");
316+
Context.ReturnVarName = $"(int32_t) {Context.ReturnVarName}";
317+
VisitPrimitiveType(PrimitiveType.Int);
389318

390319
return true;
391320
}
@@ -472,6 +401,9 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
472401
if (!VisitType(pointer, quals))
473402
return false;
474403

404+
if (pointer.IsConstCharString())
405+
return VisitPrimitiveType(PrimitiveType.String);
406+
475407
var pointee = pointer.Pointee.Desugar();
476408

477409
if (pointee is FunctionType)
@@ -567,7 +499,7 @@ public static (string func, string type, string cast) GetNAPIPrimitiveGetter(Pri
567499
case PrimitiveType.Float128:
568500
return (null, null, null);
569501
case PrimitiveType.String:
570-
return (null, null, null);
502+
return ("napi_get_value_string_utf8", "char*", null);
571503
case PrimitiveType.Null:
572504
return ("napi_get_null", null, null);
573505
case PrimitiveType.Void:
@@ -631,10 +563,23 @@ public bool VisitPrimitiveType(PrimitiveType primitive)
631563
return true;
632564

633565
case PrimitiveType.String:
566+
var size = $"_{Context.Parameter.Name}_size";
567+
Context.Before.WriteLine($"size_t {size};");
568+
Context.Before.WriteLine($"status = {func}(env, args[{Context.ParameterIndex}], " +
569+
$"nullptr, 0, &{size});");
570+
Context.Before.NewLine();
571+
572+
var buf = $"{Context.Parameter.Name}";
573+
Context.Before.WriteLine($"char* {buf} = (char*) malloc({size});");
574+
Context.Before.WriteLine($"status = {func}(env, args[{Context.ParameterIndex}], " +
575+
$"nullptr, 0, &{size});");
576+
Context.Before.WriteLine("assert(status == napi_ok);");
577+
578+
Context.Cleanup.WriteLine($"free({buf};");
579+
Context.Return.Write($"{buf}");
634580
return true;
635581

636582
case PrimitiveType.Null:
637-
638583
return true;
639584

640585
case PrimitiveType.Void:
@@ -744,42 +689,27 @@ public override bool VisitClassDecl(Class @class)
744689
private void MarshalRefClass(Class @class)
745690
{
746691
var type = Context.Parameter.Type.Desugar();
692+
693+
/*
747694
TypeMap typeMap;
748695
if (Context.Context.TypeMaps.FindTypeMap(type, out typeMap) &&
749696
typeMap.DoesMarshalling)
750697
{
751-
typeMap.CppMarshalToNative(Context);
698+
typeMap.NAPIMarshalToNative(Context);
752699
return;
753700
}
701+
*/
702+
var instance = $"{Context.Parameter.Name}_instance";
703+
Context.Before.WriteLine($"{@class.QualifiedOriginalName}* {instance};");
704+
Context.Before.WriteLine($"status = napi_unwrap(env, _this, (void**) &{instance});");
754705

755-
if (!type.SkipPointerRefs().IsPointer())
756-
{
757-
Context.Return.Write("*");
758-
759-
if (Context.Parameter.Type.IsReference())
760-
VarPrefix.Write("&");
761-
}
762-
763-
var method = Context.Function as Method;
764-
if (method != null
765-
&& method.Conversion == MethodConversionKind.FunctionToInstanceMethod
766-
&& Context.ParameterIndex == 0)
767-
{
768-
Context.Return.Write($"(::{@class.QualifiedOriginalName}*)");
769-
Context.Return.Write(Helpers.InstanceIdentifier);
770-
return;
771-
}
706+
var isPointer = type.SkipPointerRefs().IsPointer();
707+
var deref = isPointer ? "" : "*";
772708

773-
var paramType = Context.Parameter.Type.Desugar();
774-
var isPointer = paramType.SkipPointerRefs().IsPointer();
775-
var deref = isPointer ? "->" : ".";
776-
var instance = $"(::{@class.QualifiedOriginalName}*)" +
777-
$"{Context.Parameter.Name}{deref}{Helpers.InstanceIdentifier}";
709+
if (!isPointer && Context.Parameter.Type.IsReference())
710+
VarPrefix.Write("&");
778711

779-
if (isPointer)
780-
Context.Return.Write($"{Context.Parameter.Name} ? {instance} : nullptr");
781-
else
782-
Context.Return.Write($"{instance}");
712+
Context.Return.Write($"{deref}{instance}");
783713
}
784714

785715
private void MarshalValueClass(Class @class)
@@ -831,8 +761,11 @@ public override bool VisitTypedefDecl(TypedefDecl typedef)
831761

832762
public override bool VisitEnumDecl(Enumeration @enum)
833763
{
834-
Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName,
835-
Context.Parameter.Name);
764+
VisitPrimitiveType(PrimitiveType.Int);
765+
766+
Context.Return.StringBuilder.Clear();
767+
Context.Return.Write($"(::{@enum.QualifiedOriginalName}){Context.Parameter.Name}");
768+
836769
return true;
837770
}
838771

0 commit comments

Comments
 (0)