## 2 The Framework
### Registering Opcodes with Csound  
We have discussed in Section 2.1 how the opcode registration mechanism is implement through the CPOF function template plugin(). In order to use it, we just have to instantiate and invoke it with the required parameters. It signature is:  
```
template<typenameT>int plugin(Csound *csound,  const char *name,  const char *oargs,  const char *iargs,  uint32_t thread,  uint32_t flags = 0) where we have the following arguments:

* csound: a pointer to the Csound object to which we want to register our opcode. * name: the opcode name as it will be used in Csound code. * oargs: a string containing the output argument types, one identifier per argument. * iargs: a string containing the input argument types, one identifier per argument. * thread: a code to tell Csound when the opcode should be active. * flags: multithread flags (generally 0 unless the opcode accesses global resources). For the argument type identifiers, we have seen in Section 1.1.1 that the most common types are: a (audio), k (control), i (i-time), S (string) and f (fsig). The _thread_ argument, which defines what methods will be called by the opcode, can be defined by the following constants:

* thread::i: indicates init(). * thread::k: indicates kperf(). * thread::ik: indicates init() and kperf(). * thread::a: indicates aperf(). * thread::ia: indicates init() and aperf(). * thread::ika: indicates init(),kperf() and aperf(). CPOF supports the symbol on_load() as its entry point (Declared in the header file modload.h). This function needs to implemented only **once** per plugin library, and it should contain the calls to one registration function for each opcode to be added to the engine. For example, the three opcodes defined in Section 2.3 can be registered as shown in Listing 4. #include <modload.h> void csnd::on_load(Csound *csound){  csnd::plugin<Simple>(csound, \"simple\", \"i\", csnd::thread::i);  csnd::plugin<Simple>(csound, \"simple\", \"k\", \"k\", csnd::thread::k);  csnd::plugin<Simple>(csound, \"simple\", \"a\", \"a\", csnd::thread::a);  return CSOUND_OK; } These calls will register the simple _polymorphic_ opcode, which can be used with i-, k- and a-rate variables. In each instantiation of the plugin registration template, the class name is passed as an argument to it, followed by the function call. If the class defines two specific static members, otypes and itypes, to hold the types for output and input arguments, declared as

struct MyPlug : csnd::Plugin<1,2> {  static constexpr char const *otypes = \"k\";  static constexpr char const *itypes = \"ki\"; ... }; then we can use a simpler overload of the plugin registration function:template <typename T> int plugin(Csound *csound,  const char *name,  uint32_t thread,  uint32_t flags = 0)

For some classes, this might be a very convenient way to define the argument types. For other cases, where opcode polymorphism might be involved, we might re-use the same class for different argument types, in which case it is not desirable to define these statically in a class. ### Constructing and Destroying Member Variables

As opcode classes are instantiated by the Csound engine through C-language code, constructors for member variables are not invoked automatically. For member variables of non-trivial types, this may pose an issue, especially if there are specific initialisation steps to be performed at construction. All classes in the toolkit have no such requirements and do not declare constructors, but external code from other libraries might do. For these, CPOF provides a mechanism to call the member variable constructor explicitly.