/*
* Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
* for details. All rights reserved. Use of this source code is governed by a
* BSD-style license that can be found in the LICENSE file.
*/
#ifndef RUNTIME_INCLUDE_DART_API_H_
#define RUNTIME_INCLUDE_DART_API_H_
/** \mainpage Dart Embedding API Reference
*
* This reference describes the Dart Embedding API, which is used to embed the
* Dart Virtual Machine within C/C++ applications.
*
* This reference is generated from the header include/dart_api.h.
*/
#ifdef __cplusplus
#define DART_EXTERN_C extern "C"
#else
#define DART_EXTERN_C
#endif
#if defined(__CYGWIN__)
#error Tool chain and platform not supported.
#elif defined(_WIN32)
// Define bool if necessary.
#ifndef __cplusplus
typedef unsigned __int8 bool;
#endif
// Define integer types.
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#if defined(DART_SHARED_LIB)
#define DART_EXPORT DART_EXTERN_C __declspec(dllexport)
#else
#define DART_EXPORT DART_EXTERN_C
#endif
#else
/* __STDC_FORMAT_MACROS has to be defined before including <inttypes.h> to
* enable platform independent printf format specifiers. */
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include <stdbool.h>
#if __GNUC__ >= 4
#if defined(DART_SHARED_LIB)
#define DART_EXPORT \
DART_EXTERN_C __attribute__((visibility("default"))) __attribute((used))
#else
#define DART_EXPORT DART_EXTERN_C
#endif
#else
#error Tool chain not supported.
#endif
#endif
#if __GNUC__
#define DART_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#elif _MSC_VER
#define DART_WARN_UNUSED_RESULT _Check_return_
#else
#define DART_WARN_UNUSED_RESULT
#endif
#include <assert.h>
/*
* =======
* Handles
* =======
*/
/**
* An isolate is the unit of concurrency in Dart. Each isolate has
* its own memory and thread of control. No state is shared between
* isolates. Instead, isolates communicate by message passing.
*
* Each thread keeps track of its current isolate, which is the
* isolate which is ready to execute on the current thread. The
* current isolate may be NULL, in which case no isolate is ready to
* execute. Most of the Dart apis require there to be a current
* isolate in order to function without error. The current isolate is
* set by any call to Dart_CreateIsolate or Dart_EnterIsolate.
*/
typedef struct _Dart_Isolate* Dart_Isolate;
/**
* An object reference managed by the Dart VM garbage collector.
*
* Because the garbage collector may move objects, it is unsafe to
* refer to objects directly. Instead, we refer to objects through
* handles, which are known to the garbage collector and updated
* automatically when the object is moved. Handles should be passed
* by value (except in cases like out-parameters) and should never be
* allocated on the heap.
*
* Most functions in the Dart Embedding API return a handle. When a
* function completes normally, this will be a valid handle to an
* object in the Dart VM heap. This handle may represent the result of
* the operation or it may be a special valid handle used merely to
* indicate successful completion. Note that a valid handle may in
* some cases refer to the null object.
*
* --- Error handles ---
*
* When a function encounters a problem that prevents it from
* completing normally, it returns an error handle (See Dart_IsError).
* An error handle has an associated error message that gives more
* details about the problem (See Dart_GetError).
*
* There are four kinds of error handles that can be produced,
* depending on what goes wrong:
*
* - Api error handles are produced when an api function is misused.
* This happens when a Dart embedding api function is called with
* invalid arguments or in an invalid context.
*
* - Unhandled exception error handles are produced when, during the
* execution of Dart code, an exception is thrown but not caught.
* Prototypically this would occur during a call to Dart_Invoke, but
* it can occur in any function which triggers the execution of Dart
* code (for example, Dart_ToString).
*
* An unhandled exception error provides access to an exception and
* stacktrace via the functions Dart_ErrorGetException and
* Dart_ErrorGetStackTrace.
*
* - Compilation error handles are produced when, during the execution
* of Dart code, a compile-time error occurs. As above, this can
* occur in any function which triggers the execution of Dart code.
*
* - Fatal error handles are produced when the system wants to shut
* down the current isolate.
*
* --- Propagating errors ---
*
* When an error handle is returned from the top level invocation of
* Dart code in a program, the embedder must handle the error as they
* see fit. Often, the embedder will print the error message produced
* by Dart_Error and exit the program.
*
* When an error is returned while in the body of a native function,
* it can be propagated up the call stack by calling
* Dart_PropagateError, Dart_SetReturnValue, or Dart_ThrowException.
* Errors should be propagated unless there is a specific reason not
* to. If an error is not propagated then it is ignored. For
* example, if an unhandled exception error is ignored, that
* effectively "catches" the unhandled exception. Fatal errors must
* always be propagated.
*
* When an error is propagated, any current scopes created by
* Dart_EnterScope will be exited.
*
* Using Dart_SetReturnValue to propagate an exception is somewhat
* more convenient than using Dart_PropagateError, and should be
* preferred for reasons discussed below.
*
* Dart_PropagateError and Dart_ThrowException do not return. Instead
* they transfer control non-locally using a setjmp-like mechanism.
* This can be inconvenient if you have resources that you need to
* clean up before propagating the error.
*
* When relying on Dart_PropagateError, we often return error handles
* rather than propagating them from helper functions. Consider the
* following contrived example:
*
* 1 Dart_Handle isLongStringHelper(Dart_Handle arg) {
* 2 intptr_t* length = 0;
* 3 result = Dart_StringLength(arg, &length);
* 4 if (Dart_IsError(result)) {
* 5 return result
* 6 }
* 7 return Dart_NewBoolean(length > 100);
* 8 }
* 9
* 10 void NativeFunction_isLongString(Dart_NativeArguments args) {
* 11 Dart_EnterScope();
* 12 AllocateMyResource();
* 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
* 14 Dart_Handle result = isLongStringHelper(arg);
* 15 if (Dart_IsError(result)) {
* 16 FreeMyResource();
* 17 Dart_PropagateError(result);
* 18 abort(); // will not reach here
* 19 }
* 20 Dart_SetReturnValue(result);
* 21 FreeMyResource();
* 22 Dart_ExitScope();
* 23 }
*
* In this example, we have a native function which calls a helper
* function to do its work. On line 5, the helper function could call
* Dart_PropagateError, but that would not give the native function a
* chance to call FreeMyResource(), causing a leak. Instead, the
* helper function returns the error handle to the caller, giving the
* caller a chance to clean up before propagating the error handle.
*
* When an error is propagated by calling Dart_SetReturnValue, the
* native function will be allowed to complete normally and then the
* exception will be propagated only once the native call
* returns. This can be convenient, as it allows the C code to clean
* up normally.
*
* The example can be written more simply using Dart_SetReturnValue to
* propagate the error.
*
* 1 Dart_Handle isLongStringHelper(Dart_Handle arg) {