I achieve that with a helper (stripped here to the necessary), which allows to call the protected methods without any hack. Make sure to check for DataSet.State = dsInternalCalc inside OnCalcFields for fkInternalCalc fields.
type
  TClientDataSetHelper = class helper for TClientDataSet
  public
    function AssureEditing: Boolean;
    procedure InternalCalc;
  end;
function TClientDataSetHelper.AssureEditing: Boolean;
begin
  result := not (State in [dsEdit, dsInsert]);
  if result then
    Edit;
end;
procedure TClientDataSetHelper.InternalCalc;
var
  needsPost: Boolean;
  saveState: TDataSetState;
begin
  needsPost := AssureEditing;
  saveState := setTempState(dsInternalCalc);
  try
    RefreshInternalCalcFields(ActiveBuffer);
  finally
    RestoreState(saveState);
  end;
  if needsPost then
    Post;
end;
This can easily be expanded for normal calculated fields using CalculateFields. Although this shouldn't be necessary as calculated fields are recalculated whenever any other data field changes.