diff --git a/core/logic/Native.h b/core/logic/Native.h index 99257f0a..64d5d065 100644 --- a/core/logic/Native.h +++ b/core/logic/Native.h @@ -46,16 +46,14 @@ struct FakeNative FakeNative(const char *name, IPluginFunction *fun) : name(name), ctx(fun->GetParentContext()), - call(fun), - gate(NULL) + call(fun) { } - ~FakeNative(); std::string name; IPluginContext *ctx; IPluginFunction *call; - SPVM_NATIVE_FUNC gate; + ke::RefPtr wrapper; }; struct Native : public ke::Refcounted @@ -66,10 +64,10 @@ struct Native : public ke::Refcounted fake(nullptr) { } - Native(CNativeOwner *owner, FakeNative *fake) + Native(CNativeOwner *owner, std::unique_ptr&& fake) : owner(owner), native(nullptr), - fake(fake) + fake(std::move(fake)) { } @@ -77,12 +75,6 @@ struct Native : public ke::Refcounted const sp_nativeinfo_t *native; std::unique_ptr fake; - SPVM_NATIVE_FUNC func() const - { - if (native) - return native->func; - return fake->gate; - } const char *name() const { if (native) diff --git a/core/logic/ShareSys.cpp b/core/logic/ShareSys.cpp index 4fd0e8da..fd998b39 100644 --- a/core/logic/ShareSys.cpp +++ b/core/logic/ShareSys.cpp @@ -364,11 +364,11 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const sp_native_t *native } } - pPlugin->GetRuntime()->UpdateNativeBinding( - index, - pEntry->func(), - flags, - nullptr); + auto rt = pPlugin->GetRuntime(); + if (pEntry->fake) + rt->UpdateNativeBindingObject(index, pEntry->fake->wrapper, flags, nullptr); + else + rt->UpdateNativeBinding(index, pEntry->native->func, flags, nullptr); } AlreadyRefed ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv) @@ -382,11 +382,6 @@ AlreadyRefed ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const s return entry.forget(); } -FakeNative::~FakeNative() -{ - g_pSourcePawn2->DestroyFakeNative(gate); -} - void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name) { NativeCache::Result r = m_NtvCache.find(name); @@ -403,6 +398,32 @@ void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name) m_NtvCache.remove(r); } +class DynamicNative final : public INativeCallback +{ +public: + DynamicNative(SPVM_FAKENATIVE_FUNC callback, void* data) + : callback_(callback), + data_(data) + {} + + void AddRef() override { + refcount_++; + } + void Release() override { + assert(refcount_ > 0); + if (--refcount_ == 0) + delete this; + } + int Invoke(IPluginContext* ctx, const cell_t* params) override { + return callback_(ctx, params, data_); + } + +private: + size_t refcount_ = 0; + SPVM_FAKENATIVE_FUNC callback_; + void* data_; +}; + AlreadyRefed ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func) { RefPtr entry(FindNative(name)); @@ -410,14 +431,11 @@ AlreadyRefed ShareSystem::AddFakeNative(IPluginFunction *pFunc, const ch return nullptr; std::unique_ptr fake(new FakeNative(name, pFunc)); - - fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake.get()); - if (!fake->gate) - return nullptr; + fake->wrapper = new DynamicNative(func, fake.get()); CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext()); - entry = new Native(owner, fake.release()); + entry = new Native(owner, std::move(fake)); m_NtvCache.insert(name, entry); return entry.forget(); diff --git a/sourcepawn b/sourcepawn index 3ec6182c..3c76ed00 160000 --- a/sourcepawn +++ b/sourcepawn @@ -1 +1 @@ -Subproject commit 3ec6182c993a7717d81cbc6ab5dfec553de7387f +Subproject commit 3c76ed00a3908868825e04da7e588e7b4595c752