uint8_t wkpf_register_virtual_wuclass(uint16_t wuclass_id, update_function_t update, uint8_t number_of_properties, uint8_t properties[]) {
	wuclass_t *wuclass;
	if (wkpf_get_wuclass_by_id(wuclass_id, &wuclass) != WKPF_ERR_WUCLASS_NOT_FOUND) {
		DEBUG_LOG(DBG_WKPF, "WKPF: WuClass id in use while registering wuclass id %d: FAILED\n", wuclass->wuclass_id);
		return WKPF_ERR_WUCLASS_ID_IN_USE;
	}

	// Allocate memory for the new wuclass
	uint16_t size = sizeof(wuclass_t) + number_of_properties;
	dj_mem_addSafePointer((void**)&properties); // dj_mem_alloc may cause GC to run, so the address of the properties may change. this tells the GC to update our pointer if it does.
	wuclass = (wuclass_t*)dj_mem_alloc(size, CHUNKID_WUCLASS);
	dj_mem_removeSafePointer((void**)&properties);
	if (wuclass == NULL) {
		DEBUG_LOG(DBG_WKPF, "WKPF: Out of memory while registering wuclass id %d: FAILED\n", wuclass->wuclass_id);
		return WKPF_ERR_OUT_OF_MEMORY;
	}

	// Initialise memory
	memset(wuclass, 0, size);

	wuclass->wuclass_id = wuclass_id;
	wuclass->update = update;
	wuclass->number_of_properties = number_of_properties;
	for (int i=0; i<number_of_properties; i++)
		wuclass->properties[i] = properties[i];
	wkpf_register_wuclass(wuclass);

	return WKPF_OK;
}
uint8_t wkpf_create_wuobject(uint16_t wuclass_id, uint8_t port_number, dj_object *java_instance_reference /* TODO: find out what datatype to use */ ) {
	wuobject_t *wuobject;
	if (wkpf_get_wuobject_by_port(port_number, &wuobject) != WKPF_ERR_WUOBJECT_NOT_FOUND) {
		DEBUG_LOG(DBG_WKPF, "WKPF: Port %x in use while creating wuobject for wuclass id %x: FAILED\n", port_number, wuclass_id);
		return WKPF_ERR_PORT_IN_USE;
	}

	// Find the wuclass definition for this wuclass_id
	wuclass_t *wuclass;
	uint8_t retval;
	retval = wkpf_get_wuclass_by_id(wuclass_id, &wuclass);
	if (retval != WKPF_OK)
		return retval;

	// Check if an instance of the wuclass is provided if it's a virtual wuclass
	if (WKPF_IS_VIRTUAL_WUCLASS(wuclass) && java_instance_reference==0)
		return WKPF_ERR_NEED_VIRTUAL_WUCLASS_INSTANCE;

	// Allocate memory for the new wuobject
	uint8_t size_of_properties = 0;
	for(int i=0; i<wuclass->number_of_properties; i++) {
		size_of_properties += WKPF_GET_PROPERTY_DATASIZE(wuclass->properties[i]);
	}
	uint16_t size = sizeof(wuobject_t) + size_of_properties; // TODO: add space for the properties;
	dj_mem_addSafePointer((void**)&java_instance_reference); // dj_mem_alloc may cause GC to run, so the address of the wuclass and the virtual wuclass instance may change. this tells the GC to update our pointer if it does.
	dj_mem_addSafePointer((void**)&wuclass); // dj_mem_alloc may cause GC to run, so the address of the wuclass and the virtual wuclass instance may change. this tells the GC to update our pointer if it does.
	wuobject = (wuobject_t*)dj_mem_alloc(size, CHUNKID_WUCLASS);
	dj_mem_removeSafePointer((void**)&java_instance_reference);
	dj_mem_removeSafePointer((void**)&wuclass);
	if (wuobject == NULL) {
		DEBUG_LOG(DBG_WKPF, "WKPF: Out of memory while creating wuobject for wuclass %x at port %x: FAILED\n", wuclass_id, port_number);
		return WKPF_ERR_OUT_OF_MEMORY;
	}

	// Initialise memory (fixes a bug where old data corrupted the property status)
	memset(wuobject, 0, size);

	// Check if any properties need to pull their initial value from a remote node (properties that are the destination end of a link coming from another node)
	for(int i=0; i<wuclass->number_of_properties; i++) {
		if (wkpf_does_property_need_initialisation_pull(port_number, i)) {
			wuobject_property_t *property = wkpf_get_property(wuobject, i);
			wkpf_set_property_status_needs_pull(property);
			DEBUG_LOG(DBG_WKPF, "WKPF: Setting needs pull bit for property %x at port %x\n", i, port_number);
		}
	}

	wuobject->wuclass = wuclass;
	wuobject->port_number = port_number;
	wuobject->java_instance_reference = java_instance_reference;
	wuobject->need_to_call_update = false;
	if (retval != WKPF_OK)
		return retval;
	// Run update function once to initialise properties.
	wkpf_set_need_to_call_update_for_wuobject(wuobject);

	wuobject->next = wuobjects_list;
	wuobjects_list = wuobject;
	DEBUG_LOG(DBG_WKPF, "WKPF: Created wuobject for wuclass id %x at port %x\n", wuclass_id, port_number);
	return WKPF_OK;
}