diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index a207d8247fa409dd2d6c4777f3473b288171f417..952f2069c81fd667fd8b41463adab8bbb2e737b2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -89,8 +89,9 @@ public class REmbedded {
 
         if (initMainLoop) {
             context.enter();
-            RContext.getInstance().completeEmbeddedInitialization();
-            // TODO: push callbacks
+            RContext ctx = RContext.getInstance();
+            ctx.completeEmbeddedInitialization();
+            ctx.getRFFI().initializeEmbedded(ctx);
             // stay in the context TODO should we?
         }
     }
@@ -129,7 +130,9 @@ public class REmbedded {
      */
     private static void runRmainloop() {
         context.enter();
-        RContext.getInstance().completeEmbeddedInitialization();
+        RContext ctx = RContext.getInstance();
+        ctx.completeEmbeddedInitialization();
+        ctx.getRFFI().initializeEmbedded(ctx);
         int status = RCommand.readEvalPrint(context, consoleHandler);
         context.leave();
         context.close();
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
index 7b4c1ecec2669cd03be24e4aa23852b22db14b1b..b83771cec9b0c6885632d2bcc28f76b31f7ccfa7 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
@@ -196,6 +196,11 @@ final class TruffleNFI_Context extends RFFIContext {
         }
     }
 
+    @Override
+    public void initializeEmbedded(RContext context) {
+        pushCallbacks();
+    }
+
     @TruffleBoundary
     private long initCallbacksAddress() {
         // get the address of the native thread local
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContext.java
index 848300a58a428dff3e1b9f4e25df014844e6d13a..67fa9e178a4a2ed8413f148d691f529a35a6c7ec 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContext.java
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RObject;
 
@@ -101,6 +102,17 @@ public abstract class RFFIContext extends RFFI {
     public void initializeVariables(RContext context) {
     }
 
+    /**
+     * Invoked as part of the R embedded initialization just before returning back to the C user
+     * code. Should do any set-up necessary for the RFFI to be fully functional even outside the
+     * context of a down-call. At the moment the assumption is that embedded code is always single
+     * threaded and always creates exactly one context. This method shall be invoked after
+     * {@link #initialize(RContext)} and {@link #initializeVariables(RContext)}.
+     */
+    public void initializeEmbedded(RContext context) {
+        throw RInternalError.unimplemented("R Embedding not supported with " + this.getClass().getSimpleName() + " RFFI backend.");
+    }
+
     public long beforeDowncall() {
         callDepth++;
         return 0;