PNaCl - Как опубликовать сообщение из index.html в PNaCl?
Я запускаю пример hello_nacl для nacl_sdk(pepper_39) и все в порядке. Но я пытаюсь добавить что-то в index.html, чтобы отправить сообщение в PNaCl, это не работает, и я получаю сообщение об ошибке "NativeClient: модуль NaCl потерпел крах". Это мой index.html, кто-нибудь может подсказать что не так?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<script type="text/javascript">
var HelloTutorialModule = null;
function pageDidLoad() {
appendStatus('Page loaded');
HelloTutorialModule = document.getElementById('nacl_module');
HelloTutorialModule.postMessage('hello from HTML!!');
}
function appendStatus(opt_message) {
var statusField = document.getElementById('statusField');
if (statusField) {
var newElt = document.createElement("opt_message");
newElt.innerHTML = "<br>" + opt_message;
statusField.appendChild(newElt);
}
}
function handleMessage(message_event) {
appendStatus(message_event.data);
}
</script>
</head>
<body>
<div id="listener">
<script type="text/javascript">
var listener = document.getElementById('listener');
listener.addEventListener('message', handleMessage, true);
listener.addEventListener('load', pageDidLoad, true);
</script>
<h2>NaCl Module</h2>
<embed name="nacl_module"
id="nacl_module"
style="border-style: solid;"
width=200
height=200
src="newlib/hello_nacl.nmf"
type="application/x-nacl"/>
</div>
Спасибо.
Следующий код мой hello_nacl.c
/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This project demonstrates how to migrate a Windows desktop app to Native
// Client, running first as a Win32 application (define STEP1), then as a PPAPI
// plugin (define STEP2 through STEP6), and finally as a Native Client module.
// Start with STEP1 defined and the defines for STEP2 through STEP6 commented
// out. For each step in the process, un-comment the next #define, leaving the
// previous ones on. Ready, set, port!
// *** SELECT THE WIN32 PLATFORM AND RUN WITH #define STEP1 ONLY ***
// #define STEP1
// Launches the original Windows desktop application, Hello World, which runs
// as WinMain. STEP1 encloses Windows-specific functions that are used with
// the WIN32 and PPAPI platforms. These will be removed when the full PPAPI
// port is finished (STEP6)
// *** SELECT THE PPAPI PLATFORM ***
#define STEP2
// What Changed: The platform launches Chrome, which will then load a Native
// Client Module. STEP2 encloses the Native Client module APIs needed to link
// any app to the browser. The module does nothing except report
// starting/ending the function Instance_DidCreate. The Windows app does not
// run because it is not being called.
#define STEP3
// What changed: Replace WinMain with WndProc, and call it from
// Instance_DidCreate, launching hello_nacl in its own window.
// Since WndProc spins in its message loop, the call to Instance_DidCreate
// never returns.
// Close the hello_nacl window and the module initialization will finish.
#define STEP4
// What changed: In WndProc replace the message loop with a callback function.
// Now the app window and the Native Client module are running concurrently.
#define STEP5
// What changed: Instance_DidCreate calls InitInstanceInBrowserWindow rather
// than InitInstanceInPCWindow.
// The InitInstanceInBrowserWindow uses postMessage to place text (now "Hello,
// Native Client") in the web page instead of opening and writing to a window.
#define STEP6
// What changed: All the Windows code is def'd out, to prove we are
// PPAPI-compliant. The functional code that is running is the same as STEP5.
// *** SELECT THE NACL64 PLATFORM AND RUN ***
// What changed: The code is the same as STEP6, but you are using the SDK
// toolchain to compile it into a nexe. The module is now running as a real
// Native Client executable in a NaCl sandbox, with nacl-gdb attached.
// *** RUN YOUR MODULE IN THE WILD ***
// You can run your nexe outside of Visual Studio, directly from Chrome by
// following these steps:
// - Build STEP6 and verify the file
// <project directory>/NaCl64/newlib/Debug/hello_nacl_64.nexe exists
// - Copy the folder <project directory> into your NaCl SDK's example
// directory.
// - Go to the NaCl SDK directory and launch the httpd.py server.
// - Launch Chrome, go to about:flags and enable the Native Client flag and
// relaunch Chrome
// - Point Chrome at http: //localhost:5103/hello_nacl
#ifdef STEP6
// remove Windows-dependent code.
#undef STEP1
#undef STEP3
#undef STEP4
#define NULL 0
#else
// includes for Windows APIs.
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#endif
#ifdef STEP2
// includes for PPAPI
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
#include "ppapi/c/ppp_messaging.h"
#include <string.h>
#include <stdio.h>
#include <time.h>
// Native Client APIs
static PPB_Messaging* ppb_messaging_interface = NULL;
static PPB_Var* ppb_var_interface = NULL;
static PPB_Core* ppb_core_interface = NULL;
PP_Instance myInstance;
int InitInstanceInPCWindow();
void InitInstanceInBrowserWindow();
#endif
#ifdef STEP4
// Implements message handling in a callback function.
void HelloWorldCallbackFun(void* user_data, int32_t result);
struct PP_CompletionCallback HelloWorldCallback = {
HelloWorldCallbackFun, NULL };
void HelloWorldCallbackFun(void* user_data, int32_t result) {
MSG uMsg;
if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&uMsg);
DispatchMessage(&uMsg);
}
ppb_core_interface->CallOnMainThread(100, HelloWorldCallback, 0);
}
#endif
#ifdef STEP2
// The basic framework needed for all Native Client Modules. Handles creation
// of the module instance and initial handshake with the browser.
/**
* Creates new string PP_Var from C string. Useful utility for
* message-handling.
*/
static struct PP_Var CStrToVar(const char* str) { if (ppb_var_interface !=
NULL) { return ppb_var_interface->VarFromUtf8(str, strlen(str)); } return
PP_MakeUndefined(); }
void InitInstanceInBrowserWindow() {
// Pass the text to the browser page, there is no separate app window
// anymore. The text is added as a new element to the page, it does not
// appear in the module's embed view.
ppb_messaging_interface->PostMessage(myInstance, CStrToVar("Hello, Native Client! XDDXDXD"));
}
/**
* Called when the NaCl module is instantiated on the web page.
*/
static PP_Bool Instance_DidCreate(PP_Instance instance,
uint32_t argc,
const char* argn[],
const char* argv[]) {
myInstance = instance;
ppb_messaging_interface->PostMessage(instance,
CStrToVar("Start Instance_DidCreate"));
#ifdef STEP5
// Will be included in STEP5 and STEP6
// Uses messaging to relay text to the module's view on the web page
InitInstanceInBrowserWindow();
#else
#ifdef STEP3
// Will be included in STEP3 and STEP4 only
// Uses WndProc to place text in a window separate from the browser.
InitInstanceInPCWindow();
#endif
#endif
ppb_messaging_interface->PostMessage(instance,
CStrToVar("End Instance_DidCreate"));
return PP_TRUE;
}
/**
* Called when the NaCl module is destroyed.
*/
static void Instance_DidDestroy(PP_Instance instance) {
ppb_messaging_interface->PostMessage(instance,
CStrToVar("Instance_DidDestroy"));
}
/**
* Called when the position, the size, or the clip rect of the element in the
* browser that corresponds to this NaCl module has changed.
*/
static void Instance_DidChangeView(PP_Instance instance,
PP_Resource view_resource) {
ppb_messaging_interface->PostMessage(instance,
CStrToVar("Instance_DidChangeView"));
}
/**
* Notification that the given NaCl module has gained or lost focus.
*/
static void Instance_DidChangeFocus(PP_Instance instance,
PP_Bool has_focus) {
ppb_messaging_interface->PostMessage(instance,
CStrToVar("Instance_DidChangeFocus"));
}
/**
* Handler that gets called after a full-frame module is instantiated based on
* registered MIME types. This function is not called on NaCl modules. This
* function is essentially a place-holder for the required function pointer in
* the PPP_Instance structure.
*/
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
/* NaCl modules do not need to handle the document load function. */
ppb_messaging_interface->PostMessage(instance,
CStrToVar("Instance_HandleDocumentLoad...."));
return PP_FALSE;
}
static void HandleMessage(PP_Instance instance, struct PP_Var message){
//ppb_messaging_interface->PostMessage(instance, CStrToVar("Get Message From HTML"));
}
/**
* Entry points for the module.
* Initialize needed interfaces: PPB_Core, PPB_Messaging and PPB_Var.
*/
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id,
PPB_GetInterface get_browser) {
ppb_messaging_interface = (PPB_Messaging*)
get_browser(PPB_MESSAGING_INTERFACE);
ppb_var_interface = (PPB_Var*)get_browser(PPB_VAR_INTERFACE);
ppb_core_interface = (PPB_Core*)get_browser(PPB_CORE_INTERFACE);
return PP_OK;
}
/**
* Returns an interface pointer for the interface of the given name, or NULL
* if the interface is not supported.
*/
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
&Instance_DidCreate,
&Instance_DidDestroy,
&Instance_DidChangeView,
&Instance_DidChangeFocus,
&Instance_HandleDocumentLoad,
//&HandleMessage,
};
return &instance_interface;
}
return NULL;
}
/**
* Called before the plugin module is unloaded.
*/
PP_EXPORT void PPP_ShutdownModule() {
}
#endif
// **** Application Code ****
#ifdef STEP1
// Desktop Windows Hello World app. Native Client agnostic.
static TCHAR szWindowClass[] = _T("win32app");
static TCHAR szTitle[] = _T("hello_nacl");
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// WinMain
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow) {
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex)) {
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("hello_nacl"),
0);
return 1;
}
hInst = hInstance;
hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) {
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("hello_nacl"),
0);
return 1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
// WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, World!");
switch (message) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
#endif
#ifdef STEP3
// Replace WinMain with InitInstanceInPCWindow so the Native Client Module can
// launch the original application. Note the inclusion of a message-handling
// loop. STEP4 will replace the loop with a callback.
HINSTANCE g_hInstance = NULL;
HWND g_hWnd = NULL;
int InitInstanceInPCWindow() {
WNDCLASSEX winClass; MSG uMsg;
memset(&uMsg,0,sizeof(uMsg));
winClass.lpszClassName = _T("MY_WINDOWS_CLASS");
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
winClass.lpfnWndProc = WndProc;
winClass.hInstance = g_hInstance;
winClass.hIcon = NULL;
winClass.hIconSm = NULL;
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
if (!RegisterClassEx(&winClass))
return E_FAIL;
g_hWnd = CreateWindowEx(
0, _T("MY_WINDOWS_CLASS"),
_T("hello_nacl"), WS_OVERLAPPEDWINDOW,
0, 0, 640, 480, NULL, NULL, g_hInstance, NULL);
if (g_hWnd == NULL)
return E_FAIL;
ShowWindow(g_hWnd, 1);
UpdateWindow(g_hWnd);
#ifdef STEP4
// Skip the message loop, schedule a callback instead to periodically check
// for messages. Here we schedule at 100ms intervals.
ppb_core_interface->CallOnMainThread(100, HelloWorldCallback, 0);
return 0;
#else
// Main message loop, Windows style.
while(uMsg.message != WM_QUIT) {
if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage( &uMsg );
DispatchMessage( &uMsg );
}
}
return uMsg.wParam;
#endif
}
#endif
1 ответ
В этом примере много дополнительного кода, но здесь есть проблема:
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
static PPP_Instance instance_interface = {
&Instance_DidCreate,
&Instance_DidDestroy,
&Instance_DidChangeView,
&Instance_DidChangeFocus,
&Instance_HandleDocumentLoad,
//&HandleMessage,
};
return &instance_interface;
}
return NULL;
}
Когда вы отправляете сообщение в свой модуль, эта функция вызывается с запросом PPP_Messaging;1.0
интерфейс. Этот код не обрабатывает этот случай, поэтому он возвращает NULL вызывающей стороне, которая затем вылетает.
Это нежелательное поведение (оно, вероятно, должно выдавать ошибку), но это не очень удивительно.
Чтобы исправить эту ошибку, вам нужно вернуть интерфейс, когда PPP_MESSAGING_INTERFACE
запрашивается:
...
} else if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
static PPP_Messaging messaging_interface = {
&HandleMessage,
};
return &messaging_interface;
}