본문으로 건너뛰기

libraries/eosiolib/contracts/eosio/dispatcher.hpp

Namespaces

Name
eosio

Defines

Name
EOSIO_DISPATCH(TYPE, MEMBERS)

Macros Documentation

define EOSIO_DISPATCH

#define EOSIO_DISPATCH(
TYPE,
MEMBERS
)
extern "C" { \
[[eosio::wasm_entry]] \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
if( code == receiver ) { \
switch( action ) { \
EOSIO_DISPATCH_HELPER( TYPE, MEMBERS ) \
} \
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
} \
} \
} \

Parameters:

  • TYPE - The class name of the contract
  • MEMBERS - The sequence of available actions supported by this contract

Note: To be able to use this macro, the contract needs to be derived from eosio::contract

Convenient macro to create contract apply handler

Example:

EOSIO_DISPATCH( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) )

Source code

#pragma once
#include "action.hpp"

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/std_tuple.hpp>

#include <boost/mp11/tuple.hpp>

namespace eosio {


template<typename Contract, typename FirstAction>
bool dispatch( uint64_t code, uint64_t act ) {
if( code == FirstAction::get_account() && FirstAction::get_name() == act ) {
Contract().on( unpack_action_data<FirstAction>() );
return true;
}
return false;
}


template<typename Contract, typename FirstAction, typename SecondAction, typename... Actions>
bool dispatch( uint64_t code, uint64_t act ) {
if( code == FirstAction::get_account() && FirstAction::get_name() == act ) {
Contract().on( unpack_action_data<FirstAction>() );
return true;
}
return eosio::dispatch<Contract,SecondAction,Actions...>( code, act );
}




template<typename T, typename... Args>
bool execute_action( name self, name code, void (T::*func)(Args...) ) {
size_t size = action_data_size();

//using malloc/free here potentially is not exception-safe, although WASM doesn't support exceptions
constexpr size_t max_stack_buffer_size = 512;
void* buffer = nullptr;
if( size > 0 ) {
buffer = max_stack_buffer_size < size ? malloc(size) : alloca(size);
read_action_data( buffer, size );
}

std::tuple<std::decay_t<Args>...> args;
datastream<const char*> ds((char*)buffer, size);
ds >> args;

T inst(self, code, ds);

auto f2 = [&]( auto... a ){
((&inst)->*func)( a... );
};

boost::mp11::tuple_apply( f2, args );
if ( max_stack_buffer_size < size ) {
free(buffer);
}
return true;
}


// Helper macro for EOSIO_DISPATCH_INTERNAL
#define EOSIO_DISPATCH_INTERNAL( r, OP, elem ) \
case eosio::name( BOOST_PP_STRINGIZE(elem) ).value: \
eosio::execute_action( eosio::name(receiver), eosio::name(code), &OP::elem ); \
break;

// Helper macro for EOSIO_DISPATCH
#define EOSIO_DISPATCH_HELPER( TYPE, MEMBERS ) \
BOOST_PP_SEQ_FOR_EACH( EOSIO_DISPATCH_INTERNAL, TYPE, MEMBERS )


#define EOSIO_DISPATCH( TYPE, MEMBERS ) \
extern "C" { \
[[eosio::wasm_entry]] \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
if( code == receiver ) { \
switch( action ) { \
EOSIO_DISPATCH_HELPER( TYPE, MEMBERS ) \
} \
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
} \
} \
} \

}

Updated on 2022-12-05 at 15:38:08 +0000