# Your first script

Being an embedded scripting library there isn't much that AngelScript allows the scripts to do by themselves, so the first thing the application must do is to register the interface that the script will have to interact with the application. The interface may consist of functions, variables, and even complete classes.

    // Create the script engine
    asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

    // Set the message callback to receive information on errors in human readable form.
    // It's recommended to do this right after the creation of the engine, because if
    // some registration fails the engine may send valuable information to the message
    // stream.
    r = engine->SetMessageCallback(asFUNCTION(msgCallback), 0, asCALL_CDECL); assert( r >= 0 );

    // AngelScript doesn't have a built-in string type, as there is no definite standard
    // string type for C++ applications. Every developer is free to register it's own string type.
    // The SDK do however provide a standard add-on for registering a string type, so it's not
    // necessary to register your own string type if you don't want to.
    RegisterScriptString(engine);

    // Register the function that we want the scripts to call
    r = engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL); assert( r >= 0 );

After the engine has been configured, the next step is to compile the scripts that should be executed.

The following is our script that will call the registered `print` function to write `Hello world` on the standard output stream. Let's say it's stored in the file `test.as`.

      void main()
      {
        print("Hello world\n");
      }

Here's the code for loading the script file and compiling it.

    // Load the entire script file into the buffer
    string script;
    LoadScriptFile("test.as", &script);

    // Add the script to the module as a section. If desired, multiple script
    // sections can be added to the same module. They will then be compiled
    // together as if it was one large script.
    asIScriptModule *mod = engine->GetModule("MyModule", asGM_ALWAYS_CREATE);
    mod->AddScriptSection("test.as", script.c_str(), script.length());

    // Build the module
    r = mod->Build();
    if( r < 0 )
    {
      // An error occurred. Instruct the script writer to fix the compilation errors
      // that were listed in the output stream.
      printf("Please correct the errors in the script and try again.\n");
      return;
    }

The last step is to identify the function that is to be called, and set up a context for executing it.

    // Find the function that is to be called.
    int funcId = mod->GetFunctionIdByDecl("void main()");
    if( funcId < 0 )
    {
      // The function couldn't be found. Instruct the script writer to include the
      // expected function in the script.
      printf("The script must have the function 'void main()'. Please add it and try again.\n");
      return;
    }

    // Create our context, prepare it, and then execute
    asIScriptContext *ctx = engine->CreateContext();
    ctx->Prepare(funcId);
    r = ctx->Execute()
    if( r != asEXECUTION_FINISHED )
    {
      // The execution didn't complete as expected. Determine what happened.
      if( r == asEXECUTION_EXCEPTION )
      {
        // An exception occurred, let the script writer know what happened so it can be corrected.
        printf("An exception '%s' occurred. Please correct the code and try again.\n", ctx->GetExceptionString());
      }
    }

The exception handling above is very basic. The application may also obtain information about line number, function, call stack, and even values of local and global variables if wanted.

Don't forget to clean up after you're done with the engine.

    // Clean up
    ctx->Release();
    engine->Release();

## Helper functions

The following are the implementation of the helper functions used in the example above.

    // Forward the compiler message to the standard output stream
    void msgCallback(const asSMessageInfo *msg, void *param)
    {
      const char *type = "Error";
      if( msg->type == asMSGTYPE_INFORMATION )
        type = "Info";
      else if( msg->type == asMSGTYPE_WARNING )
        type = "Warning";

      printf("%s (%d, %d): %s = %s\n", msg->section, msg->row, msg->col, type, msg->message);
    }

    // Print the script string to the standard output stream
    void print(string &msg)
    {
      printf(msg.c_str());
    }

    // Load the entire script file into a string buffer
    void LoadScriptFile(const char *fileName, string &script)
    {
      FILE *f = fopen("test.as", "rb");

      // Determine the size of the file
      fseek(f, 0, SEEK_END);
      int len = ftell(f);
      fseek(f, 0, SEEK_SET);

      // Load the entire file in one call
      script.resize(len);
      fread(&script[0], len, 1, f);

      fclose(f);
    }