Skip to content

Handle exceptions in C bindings#2980

Draft
MandelbrotInferno wants to merge 1 commit intof3d-app:masterfrom
MandelbrotInferno:Exception-Handling-C-Bindings-Feature
Draft

Handle exceptions in C bindings#2980
MandelbrotInferno wants to merge 1 commit intof3d-app:masterfrom
MandelbrotInferno:Exception-Handling-C-Bindings-Feature

Conversation

@MandelbrotInferno
Copy link
Copy Markdown

Describe your changes

All of the C bindings for libf3d now handle exceptions inside of them and log the relevant warning/error message. Where necessary, I have also added the necessary descriptions in the C binding comments.

Issue ticket number and link if any

#2763

Checklist for finalizing the PR

  • I have performed a self-review of my code
  • I have added tests for new features and bugfixes
  • I have added documentation for new features
  • If it is a modifying the libf3d API, I have updated bindings
  • If it is a modifying the .github/workflows/versions.json, I have updated docker_timestamp

Continuous integration

\ci fast

@mwestphal mwestphal self-requested a review March 29, 2026 08:56
Copy link
Copy Markdown
Member

@mwestphal mwestphal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please request a review whenever you need by using github review mechanism (top right).

@MandelbrotInferno
Copy link
Copy Markdown
Author

Please request a review whenever you need by using github review mechanism (top right).

Ah yes. I forgot to request that. Thanks for the heads up:)

@mwestphal
Copy link
Copy Markdown
Member

Please request a review whenever you need by using github review mechanism (top right).

Ah yes. I forgot to request that. Thanks for the heads up:)

No worries, I'm just explaining the process as usual :)

Comment thread c/utils_c_api.cxx
f3d::log::error("Failed to allocate memory for char*: ", e.what());
}

return nullptr;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please document that behavior

Comment thread c/utils_c_api.cxx
}

if (out_count)
catch (const std::bad_alloc& e)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that for the new ? im not sure we want to catch that. wdyt @Meakk @AoGao-Kedoka ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i also think it's unnecessary. If memory is full, the program is already in a critical state. The catch wouldn't help anyways.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say we should catch f3d specific exceptions, and fallback on a generic std::exception to catch the rest of them, so bad_alloc is too specific.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we should catch all exceptions in all methods ?

At least thats not what we have been doing in other c bindings.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you see fit. I agree we should be consistent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets not catch everthing, but only what we throw ( or can throw by our usages in the C binding)

Comment thread c/utils_c_api.cxx
auto collapsed = f3d::utils::collapsePath(p, base);
return f3d_utils_strdup(collapsed.string());
}
catch (...)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catch specific exceptions, not everything

Comment thread c/utils_c_api.cxx
std::string regex = f3d::utils::globToRegex(glob, path_separator);
return f3d_utils_strdup(regex);
}
catch (const std::exception& e)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catch specific exceptions, not everything

Copy link
Copy Markdown
Member

@mwestphal mwestphal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've only reviewed utils for now, to make sure we are on the same page regarding what is expected here.

@MandelbrotInferno
Copy link
Copy Markdown
Author

MandelbrotInferno commented Mar 30, 2026

I've only reviewed utils for now, to make sure we are on the same page regarding what is expected here.

Thanks! Will try to fix the mentioned issues. I did however notice that in some of the C bindings that exception handling was written for we handled everything eg:

f3d_engine_t* f3d_engine_create(int offscreen)
{
  try
  {
    f3d::engine* eng = new f3d::engine(f3d::engine::create(offscreen != 0));
    return reinterpret_cast<f3d_engine_t*>(eng);
  }
  catch (std::exception& e)
  {
    f3d::log::error("Failed to create engine: ", e.what());
    return nullptr;
  }
}

The above is in the engine_c_api.cxx file for example. Should I go ahead and modify those too in order to ensure only the required specific exceptions are handled?

@AoGao-Kedoka
Copy link
Copy Markdown
Contributor

I've only reviewed utils for now, to make sure we are on the same page regarding what is expected here.

Thanks! Will try to fix the mentioned issues. I did however notice that in some of the C bindings that exception handling was written for we handled everything eg:

f3d_engine_t* f3d_engine_create(int offscreen)
{
  try
  {
    f3d::engine* eng = new f3d::engine(f3d::engine::create(offscreen != 0));
    return reinterpret_cast<f3d_engine_t*>(eng);
  }
  catch (std::exception& e)
  {
    f3d::log::error("Failed to create engine: ", e.what());
    return nullptr;
  }
}

The above is in the engine_c_api.cxx file for example. Should I go ahead and modify those too in order to ensure only the required specific exceptions are handled?

Engine is where everything getting initialized and it would be quite amount of work to be specific here. But I defer to @mwestphal

@mwestphal
Copy link
Copy Markdown
Member

mwestphal commented Mar 30, 2026

I've only reviewed utils for now, to make sure we are on the same page regarding what is expected here.

Thanks! Will try to fix the mentioned issues. I did however notice that in some of the C bindings that exception handling was written for we handled everything eg:

f3d_engine_t* f3d_engine_create(int offscreen)
{
  try
  {
    f3d::engine* eng = new f3d::engine(f3d::engine::create(offscreen != 0));
    return reinterpret_cast<f3d_engine_t*>(eng);
  }
  catch (std::exception& e)
  {
    f3d::log::error("Failed to create engine: ", e.what());
    return nullptr;
  }
}

The above is in the engine_c_api.cxx file for example. Should I go ahead and modify those too in order to ensure only the required specific exceptions are handled?

Engine is where everything getting initialized and it would be quite amount of work to be specific here. But I defer to @mwestphal

Indeed, in that specific case, for the sake of simplicty and brevity we decided to catch everything, but its better to be specific when possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants