Что удалось
1. Вызов методов и свойств
2. Установка свойств
3. Вызов объекта как функции
4. Создание объекта (new) через объект
5. Применение енумератора к объекту
export interface NetObjectinterface {
(): void;
Id: number;
isNetObject: boolean;
}
function getNetObject(id: number): NetObjectinterface {
let netObject = <NetObjectinterface>function (start: number) { };
netObject.Id = id;
netObject.isNetObject = true;
return netObject;
}
export class NetObject {
static GetNetObject(id: number) { return getNetObject(id); }
}
export var NetObjectHandler: ProxyHandler<NetObject> = {
get: (target: NetObject, name: any) => {
if (name === Symbol.iterator) {
return function () {
let nextIndex=5;
return {
next: function () {
return nextIndex < 10 ?
{ value: nextIndex++, done: false } :
{ value: undefined, done: true };
}
}
}
}
if (name.startsWith('_')) {
return "propery";
}
return (...args: any[]) => {
let res: string = name;
for (let param of args) {
res += ", " + (typeof param);
if (typeof param == "object") {
res += ", " + param().Id.toString();
}
else {
res += ", " + param.toString();
}
}
return res;
}
},
set: function (target, prop, value, receiver) {
console.log("called: " + prop.toString() + " = " + value);
return true;
},
apply: (target, that, args) => {
if (args.length == 0)
return target;
return args[0];
},
construct: (target, argumentsList, newTarget) => {
var res = NetObject.GetNetObject(5);
return new Proxy(res, NetObjectHandler)
}
}
И использование
submit(user:User) {
//let res = new NetObject(1);
let res = NetObject.GetNetObject(1);
let obj:any = new Proxy(res, NetObjectHandler);
this.PropertyStr = obj._Property;
obj._Property = 5;
try{
this.PropertyStr = obj().Id.toString();
this.MethodStr = obj("Hello");
this.ConstructStr = new obj(3)().Id.toString();
}
catch (e) {
console.log("ошибка " + e);
}
for (let i of obj)
console.log(i);
let p = new Proxy([1,2,3], {
enumerate: (target) => {
return ["a", "b", "c"];
}
});
for (var x of p) { // "called"
console.log(x); // "a"
}
}
Так как не нашел финализатора думаю удалять объекты через ()
Например StringBuilder при вызове методов возвращает ссылку на себя
let =Net.GetType("System.Text.StringBuilder");
let sb= new StringBuilder("Первый");
sb.Append("Новая Строка")(1);
sb.AppendLine()(1);
sb.Append("Вторая Строка")(1);
sb.AppendLine()(1);
sb.AppendFormat("AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина )(1);
sb.AppendLine()(1);
sb(1);
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
F>> Не многие юзеры начинаю с вики, и в итоге задают глупые вопросы. S> Ну в Вики мало чего. Нужно реальный код смотреть. А его не так и много. Но разобрался.
Если есть чёткое понимание, что нужно сделать — но не знаешь куда копать — всегда можно спросить на CEF forum. Там ткнут быстро в нужные точки. В вики покрыты основные/частые вопросы. Безусловно в отсутствии серьезных врайтеров вики — информации может и маловато. Но потом понимаешь что там в общем-то всё было, просто информация часто оказывается недопонятной. Так же абсолютно нельзя игнорировать документацию к API.
F>> PS: Потом, когда получится что-то интересное (если это публично доступно), не забудь похвастаться в соответствующим разделе форума по CEF. S> Спасибо! А то руки опускаются, что никому это не интересно
Я не очень понимаю что именно ты делаешь на самом деле.
Здравствуйте, Serginio1, Вы писали:
S>Кстати а не подскажешь как мне прикрутить аналог финализатора. S>Нашел <span class='lineQuote level1'>S>Make weak references to JavaScript Objects</span> S> К обычному JS у меня не получилось прикрутить. Может как то из CEF можно прикрутить финализатор?
Финализатор чего? Если речь идёт о JS объекте — то никак. Можешь полностью игнорировать финализаторы V8 т.к. половина вызывается,
другая половина — вызвана не будет т.к. persistent handles мешают этому. Кроме того by-design — при разрушении контекста (JS мира),
вся куча дропается и всё. Никаких вызовов финализаторов не будет by-design (V8).
Если речь идёт о объектах CEF — то — как только счетчик ссылок становится равным 0 — пора вычищать связанные с объектом вещи. Это
широко используется в CEF и клиентах (в нэйтиве дёргается деструктор, для CefGlue — я вызываю Dispose(true), в текущих версиях — только
для некоторых объектов — моя старая ошибка что этого не делал изначально).
Если речь идёт о CEF V8Context и связанных объектах — то после OnContextDestroy никаких ссылок не должно оставаться на V8Context.
Это значит что ты должен здесь всё связанное с V8 высвободить. (Контекст принадлежит фрейму, но контекст != фрейм — один и тот же фрейм
может иметь несколько конекстов, ну не одновременно, а просто перезагрузка контента и т.п. Но вообще about:blank — затем URL — вот один
фрейм но два контекста, при этом первый контекст высвобождается почти сразу, поэтому желательно так же минимизировать работу
в OnContextCreated — хотя это и не всегда возможно — ведь в динамических фреймах — URL будет как раз тот самый about:blank).
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, Serginio1, Вы писали:
F>>> Не многие юзеры начинаю с вики, и в итоге задают глупые вопросы. S>> Ну в Вики мало чего. Нужно реальный код смотреть. А его не так и много. Но разобрался. F> Если есть чёткое понимание, что нужно сделать — но не знаешь куда копать — всегда можно спросить на CEF forum. Там ткнут быстро в нужные точки. В вики покрыты основные/частые вопросы. Безусловно в отсутствии серьезных врайтеров вики — информации может и маловато. Но потом понимаешь что там в общем-то всё было, просто информация часто оказывается недопонятной. Так же абсолютно нельзя игнорировать документацию к API.
Эх проблемы у меня с англицким 1С ник я. F>>> PS: Потом, когда получится что-то интересное (если это публично доступно), не забудь похвастаться в соответствующим разделе форума по CEF. S>> Спасибо! А то руки опускаются, что никому это не интересно F> Я не очень понимаю что именно ты делаешь на самом деле.
Я делаю порт для использования .Net классов в Angular 2/
Например есть приложение на WPF или UWP, но его нужно перенести на линукс.
Мы можем взять компоненты Ангулар например Компоненты от PrimeNG
и использовать .Net Core классы
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Эх проблемы у меня с англицким 1С ник я.
У меня тоже проблемы с английским. Нужно просто пытаться. Кроме того там половина интернета пишет как попало, причём нэйтивы тоже. Так шо забей. Если не пытаться — то точно не получится.
S> Я делаю порт для использования .Net классов в Angular 2/ S>Например есть приложение на WPF или UWP, но его нужно перенести на линукс. S>Мы можем взять компоненты Ангулар например Компоненты от PrimeNG S> и использовать .Net Core классы
Для этого нужно такое сильно взаимодействие? Не лучше ли выставить некий "сервисный" слой в браузер? Не, то что ты делаешь — я приблизительно понимаю. Выглядит круто — но именно есть ли в этом необходимость — я немного сомневаюсь. Ну т.е. на примере: использовать StringBuilder — явно оверкил, массив и push в него — гораздо лучше для JS. Не, с другой стороны я понимаю, что если мы позволяем работать с любым C# объектом — то в общем-то уже принципиальных ограничений нет.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, Serginio1, Вы писали:
S>>Эх проблемы у меня с англицким 1С ник я. F> У меня тоже проблемы с английским. Нужно просто пытаться. Кроме того там половина интернета пишет как попало, причём нэйтивы тоже. Так шо забей. Если не пытаться — то точно не получится.
S>> Я делаю порт для использования .Net классов в Angular 2/ S>>Например есть приложение на WPF или UWP, но его нужно перенести на линукс. S>>Мы можем взять компоненты Ангулар например Компоненты от PrimeNG S>> и использовать .Net Core классы F> Для этого нужно такое сильно взаимодействие? Не лучше ли выставить некий "сервисный" слой в браузер? Не, то что ты делаешь — я приблизительно понимаю. Выглядит круто — но именно есть ли в этом необходимость — я немного сомневаюсь. Ну т.е. на примере: использовать StringBuilder — явно оверкил, массив и push в него — гораздо лучше для JS. Не, с другой стороны я понимаю, что если мы позволяем работать с любым C# объектом — то в общем-то уже принципиальных ограничений нет.
Ну это просто для примера.
Я в 1С использую для доступа к торговому оборудованию, к Вэб сервисам по ws протоколам,
котовым компонентам. AngleSharp конечно бессмысленно, но например работа с Linux, Excel, Word, OpenXML,ADO и Net
Кроме того сделаю передачу JS объектов на сторону .Net с использованием через DynamicObject.
На самом деле можно сделать определенную конфигурацию CEF для всех платформ и можно делать кроспалатформенные декстопные приложения.
Намного легче чем на том же Electron. Или по крайней мере её альтернатива.
.Net Core развивается.
Ну и жалко, что идея для 1С пропадает. Покажу реализацию, может кого и заинтересует.
Там так или иначе большой пласт всего поднят.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, fddima, Вы писали:
F> Если речь идёт о объектах CEF — то — как только счетчик ссылок становится равным 0 — пора вычищать связанные с объектом вещи. Это F>широко используется в CEF и клиентах (в нэйтиве дёргается деструктор, для CefGlue — я вызываю Dispose(true), в текущих версиях — только F>для некоторых объектов — моя старая ошибка что этого не делал изначально).
Я поясню тут момент:
В CEF некоторые API могут показаться незавершенными. Примером может быть:
bool CefCookieManager::VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor);
///
// Interface to implement for visiting cookie values. The methods of this class
// will always be called on the IO thread.
///
/*--cef(source=client)--*/class CefCookieVisitor : public virtual CefBase {
public:
///
// Method that will be called once for each cookie. |count| is the 0-based
// index for the current cookie. |total| is the total number of cookies.
// Set |deleteCookie| to true to delete the cookie currently being visited.
// Return false to stop visiting cookies. This method may never be called if
// no cookies are found.
///
/*--cef()--*/virtual bool Visit(const CefCookie& cookie, int count, int total,
bool& deleteCookie) =0;
};
Жирным я выделил именно это место. Как же нам быть, если мы хотим посетить куки, дождаться когда это произойдет и пойти дальше? Так вот "хитрость" (для меня это именно хитрость — я долгое время в упор этого не замечал), в том, что когда объект CefCookieVisitor уничтожается — означает что VisitAllCookies завершил свою работу (по той или иной причине — всё отвизитили, или решили прервать в Visit).
Теперь развернуто:
S> Ну получается около 15 000 вызовов в секунду. Правда в отладчике. Плюс еще накладные на Proxy появятся. Но приемлемо.
Для того что бы взять хоть какой-то baseline — возьми cefclient -> Tests -> Other Tests -> Javascript Performance Tests первый и второй. Один из них (второй) делал я, потом его допилили и втащили в cefclient, — что именно он меряет теперь я уже не очень уверен — да и вообще забыл уже всё. Откусили от него как минимум .NET GC memory.
Сейчас у меня тесты эти показывают 150K-250K вызовов (от железа естественно зависит). Ну судя и комментариев — очень похоже на то что делаешь ты (посмотри там есть int -> int функция).
Но, самый быстрый биндинг был в cefglue-v1. Даже быстрее чем в родном C++, потому, что накладные расходы на маршалинг в C++ типы я убрал, оставшись в этой части на C API. И если я не ошибаюсь, он делал 500K вызовов, правда полагаясь на сборку мусора (ненужных CefV8Value), и затем я переделал так, что бы мусора не создавалось — немного медленне... 350K, — но в целом, это лучше чем жрать память, да и выхватывать косяки с временем жизни объектов тоже неинтересно. Но правда точные цифры я забыл. Но то что в cefclient — это не максимум который можно выжать — это точно.
К сожалению обёртка вокруг V8 выполненная в стиле CEF — не самая быстрая по определению. Ну, а передача ещё и сложных аргументов — совсем ховайся. Приблизительно поэтому и следует избегать активного использования простых акцессоров. Хотя для большинства задач и 1K хватит с головой.
У тебя наверное действительно из-за дебага такая беда (CEF релизный или дебажный? если дебажный — то точно из-за этого). Думаю даже с прокси нужно стремиться к 100К вызовов должно быть стабильно.
Так же отмечу: asynchronous vs synchornous режимы — делая всю работу синхронно — ты создашь кучу мусора в V8, поэтому наиболее оптимально и более близко к реальности — всё же хоть иногда делать yield (setTimeout(0)), да бы другим задачам (в том числе и рендер) на основном потоке осталось время поразмышлять. И мусор раньше собирался только в это время. Сейчас возможно он собирается и без этого.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, Serginio1, Вы писали:
F> Я как доберусь до ответа — ты сообщения сносишь.
Да я задам вопрос, потом его решу. F> TL;DR: F> — даешь 100К вызовов; F> — меряй память;
Без JS даже ~500К.
F> Теперь развернуто:
S>> Ну получается около 15 000 вызовов в секунду. Правда в отладчике. Плюс еще накладные на Proxy появятся. Но приемлемо. F> Для того что бы взять хоть какой-то baseline — возьми cefclient -> Tests -> Other Tests -> Javascript Performance Tests первый и второй. Один из них (второй) делал я, потом его допилили и втащили в cefclient, — что именно он меряет теперь я уже не очень уверен — да и вообще забыл уже всё. Откусили от него как минимум .NET GC memory. F> Сейчас у меня тесты эти показывают 150K-250K вызовов (от железа естественно зависит). Ну судя и комментариев — очень похоже на то что делаешь ты (посмотри там есть int -> int функция). F> Но, самый быстрый биндинг был в cefglue-v1. Даже быстрее чем в родном C++, потому, что накладные расходы на маршалинг в C++ типы я убрал, оставшись в этой части на C API. И если я не ошибаюсь, он делал 500K вызовов, правда полагаясь на сборку мусора (ненужных CefV8Value), и затем я переделал так, что бы мусора не создавалось — немного медленне... 350K, — но в целом, это лучше чем жрать память, да и выхватывать косяки с временем жизни объектов тоже неинтересно. Но правда точные цифры я забыл. Но то что в cefclient — это не максимум который можно выжать — это точно. F> К сожалению обёртка вокруг V8 выполненная в стиле CEF — не самая быстрая по определению. Ну, а передача ещё и сложных аргументов — совсем ховайся. Приблизительно поэтому и следует избегать активного использования простых акцессоров. Хотя для большинства задач и 1K хватит с головой.
F> У тебя наверное действительно из-за дебага такая беда (CEF релизный или дебажный? если дебажный — то точно из-за этого). Думаю даже с прокси нужно стремиться к 100К вызовов должно быть стабильно.
F> Так же отмечу: asynchronous vs synchornous режимы — делая всю работу синхронно — ты создашь кучу мусора в V8, поэтому наиболее оптимально и более близко к реальности — всё же хоть иногда делать yield (setTimeout(0)), да бы другим задачам (в том числе и рендер) на основном потоке осталось время поразмышлять. И мусор раньше собирался только в это время. Сейчас возможно он собирается и без этого.
Да. Дебажный. Но по моему JS тормозит.
Сейчас проверю вызов без Net
и солнце б утром не вставало, когда бы не было меня
Передать в Net ссылки на методы объекта,А из Net вызвать метод об
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate int МетодОбъекта2Delegate(IntPtr self, int Число1, int Число2);
public static void CallCppMethodObject(IntPtr Self, IntPtr АдресМетода)
{
var execute = Marshal.GetDelegateForFunctionPointer<МетодОбъекта2Delegate>(АдресМетода);
var res = execute(Self, Self.ToInt32(), 777);
execute(Self, Self.ToInt32(), res);
}
Можно передавать ссылку на объект обертку с CefRefPtr<CefV8Value> и контекстом.
Только на время вызова функции из JS
Может есть другие возможности получить ссылку на CefRefPtr<CefV8Value>.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S> Можно передавать ссылку на объект обертку с CefRefPtr<CefV8Value> и контекстом. S>Только на время вызова функции из JS S>Может есть другие возможности получить ссылку на CefRefPtr<CefV8Value>.
Это наверное наиболее простой и универсальный способ как минимум для начала. Второе, если ещё не делаешь — избавляйся от них как можно раньше — т.е. нужен инт — получай инт. Тогда на долю V8Value останутсятолько сложные типы и нужно решить что тут делать. POD-ы и функции. Функции проблемнее всего — т.к. мы обычно хотим сохранить на них ссылку и дернуть когданибудь, но их нужно дропнуть в OnContextReleased.
Насчет как легче обернуть C++ объекты — не скажу. CefGlue потребляет C API и создает свои врапперы вокруг этого. Клиентская C++ библиотека делает тоже самое. Поэтому пробрасывать С++ объекты неэффективно ну и геморно.
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, Serginio1, Вы писали:
S>> Можно передавать ссылку на объект обертку с CefRefPtr<CefV8Value> и контекстом. S>>Только на время вызова функции из JS S>>Может есть другие возможности получить ссылку на CefRefPtr<CefV8Value>.
F> Это наверное наиболее простой и универсальный способ как минимум для начала. Второе, если ещё не делаешь — избавляйся от них как можно раньше — т.е. нужен инт — получай инт. Тогда на долю V8Value останутсятолько сложные типы и нужно решить что тут делать. POD-ы и функции. Функции проблемнее всего — т.к. мы обычно хотим сохранить на них ссылку и дернуть когданибудь, но их нужно дропнуть в OnContextReleased.
F> Насчет как легче обернуть C++ объекты — не скажу. CefGlue потребляет C API и создает свои врапперы вокруг этого. Клиентская C++ библиотека делает тоже самое. Поэтому пробрасывать С++ объекты неэффективно ну и геморно.
Попробую Объяснить
Создадим класс
Class JSObjectProxy
{
//
CefRefPtr<CefV8Value> JSObject;
vector<JSObjectProxy*> listProxy;
CefRefPtr<CefV8Context> context; // Или один класс содержащий контекст
// Этот метод дергаем из .Net Corebool CallJsMethod(wchar_t* method,tvarstruct* params, int argCount,wchar_t** Error)
{
здесь вызываем
JSObject_->ExecuteFunctionWithContext(callback_context_, NULL, args, retval, exception, false))
и если функция возвращает в retval JSObject то создаем JSObjectProxy
и добавляем его в listProxy, что бы ссылка не обнулилась.
}
}
vector<JSObjectProxy*> это вектор который создается в Методе Exexute
члены которого будут уничтожаться при выходе из метода.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Есть идея иметь доступ из TypeScript к методам и свойствам классов .Net. S>У меня есть опыт вызова методов .Net объектов из натива https://habrahabr.ru/users/serginio1/topics/
Если нужна кросс-платформенность возможно будет вариантом собрать всё через Mono с ключом --enable-nacl:
--enable-nacl
This configures the Mono compiler to generate code suitable to be used by Google's Native Client: http://code.google.com/p/nativeclient/
Currently this is used with Mono's AOT engine as Native Client does not support JIT engines yet.