Hello,
I have run into a bit of an issue that I uncovered when trying to import a shared interface into another module.
More specifically, when I attempt to import my shared interface, I am getting an Access violation error on line 1748 of as_context.cpp. The function is `asCContext::CallScriptFunction`, and it looks like the parameter `asCScriptFunction *func` is null.
The interesting thing is that if I remove the import of the shared interface into the module, the code works fine. I am using this shared interface in my main module, and have not yet started using it in my other modules.
The code that I am building my shared module with looks like this:
external shared interface IPlayer;
The IPlayer code looks like this:
#include "IModel.as"
shared interface IPlayer : IKeyboardEventListener, IMouseMotionEventListener, IMouseButtonEventListener, IMouseWheelEventListener, IModel
{
array<Entity> selectedUnits() const;
void setSelectedUnits(const array<Entity>& in units);
bool owner(const Entity entity) const;
bool owner(const IGameObject@ gameObject) const;
uint32 totalCredits() const;
uint32 totalPopulation() const;
uint32 totalFood() const;
uint32 totalMinerals() const;
uint32 numUnits() const;
uint32 numBuildings() const;
uint32 id() const;
const string& name() const;
void placeBuilding(Entity entity);
}
mixin class PlayerMixin
{
protected uint32 totalCredits_ = 0;
protected uint32 totalPopulation_ = 0;
protected uint32 totalFood_ = 0;
protected uint32 totalMinerals_ = 0;
protected uint32 id_ = 0;
protected string name_;
bool owner(const Entity entity) const
{
const auto scriptObjectComponent = entity.componentScriptObjectComponent();
if (bool(scriptObjectComponent) && scriptObjectComponent.get().scriptObjectHandle)
{
const auto gameObject = cast<IGameObject>(scriptObjectComponent.get().scriptObjectHandle.get());
if (gameObject !is null) return owner(gameObject);
}
return false;
}
bool owner(const IGameObject@ gameObject) const
{
auto unit = cast<IUnit>(gameObject);
if (unit !is null)
{
return unit.owner() == @this;
}
else
{
auto building = cast<IBuilding>(gameObject);
if (building !is null) return building.owner() == @this;
}
return false;
}
uint32 totalCredits() const
{
return totalCredits_;
}
uint32 totalPopulation() const
{
return totalPopulation_;
}
uint32 totalFood() const
{
return totalFood_;
}
uint32 totalMinerals() const
{
return totalMinerals_;
}
uint32 id() const
{
return id_;
}
const string& name() const
{
return name_;
}
}
IModel looks like this:
#include "IChangeListener.as"
shared interface IModel
{
void tick(const float delta);
void addChangeListener(IChangeListener@ changeListener);
void removeChangeListener(IChangeListener@ changeListener);
}
mixin class ModelMixin
{
private array<IChangeListener@> changeListeners_;
void tick(const float delta)
{
}
void addChangeListener(IChangeListener@ changeListener)
{
println("adding change listener");
changeListeners_.push_back(changeListener);
}
void removeChangeListener(IChangeListener@ changeListener)
{
for (uint i=0; i < changeListeners_.size(); i++)
{
if (@changeListeners_[i] == @changeListener)
{
changeListeners_.removeAt(i);
break;
}
}
}
protected void updateChangeListeners()
{
for (uint i=0; i < changeListeners_.size(); i++)
{
changeListeners_[i].update();
}
}
}
IChangeListener looks like this:
shared interface IChangeListener
{
void update();
}
Another way I have found to fix the issue is to make the IPlayer interface not inherit from IModel, and instead copy the definitions from IModel directly into IPlayer.
I have been able to reproduce this in version 2.32.0, as well as the latest from SVN.