-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix marshalling of bool flags in MF #3210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3210 +/- ##
==========================================
+ Coverage 72.61% 72.62% +0.01%
==========================================
Files 807 807
Lines 145077 145080 +3
Branches 16213 16213
==========================================
+ Hits 105345 105365 +20
+ Misses 35316 35297 -19
- Partials 4416 4418 +2
|
@@ -133,19 +133,19 @@ private struct MFParameter | |||
/// Specify if the factor matrices should be non-negative. | |||
/// </summary> | |||
[FieldOffset(48)] | |||
public int DoNmf; | |||
public byte DoNmf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is better than what we had before, this is still not correct.
https://docs.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=vs-2019
bool Type bool is an integral type that can have one of the two values true or false. Its size is unspecified.
https://en.cppreference.com/w/cpp/language/types
bool - type, capable of holding one of the two values: true or false. The value of sizeof(bool) is implementation defined and might differ from 1.
Instead, to make interop/marshalling work correctly on all computers - the technique we use in .NET is to ensure the ABI (application binary interface) is stable no matter the compiler/processor/etc. This means only stable-sized types can be used in the ABI that C# code P/Invokes into.
So to fix this, the libmf C code should change to have a stable ABI. I see it uses float
, int
, and bool
. For sure int
and bool
can change sizes depending on the compiler/processor. Instead, we should be using int32_t
and int8_t
on the C side. (Note: you can just have a wrapper export function in the C library that exposes the stable ABI and calls into your current code. So the main C/C++ code can remain unchanged.) #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing this out. Another iteration is pushed. Hopefully, it can address this comment.
@@ -133,19 +133,19 @@ private struct MFParameter | |||
/// Specify if the factor matrices should be non-negative. | |||
/// </summary> | |||
[FieldOffset(48)] | |||
public int DoNmf; | |||
public sbyte DoNmf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why sbyte
? Why not just byte
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's int8 in C side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it uint8_t
on the C side then?
Signed-ness doesn't really matter here. So using byte
is more appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I will change other place to match this decision.
@@ -9,25 +9,48 @@ | |||
|
|||
using namespace mf; | |||
|
|||
EXPORT_API(mf_parameter) make_param(const mf_parameter_bridge *param_bridge) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this needs EXPORT_API
does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes!
param.eta = param_bridge->eta; | ||
param.alpha = param_bridge->alpha; | ||
param.c = param_bridge->c; | ||
param.do_nmf = static_cast<bool>(param_bridge->do_nmf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of static cast, would it be better to use param_bridge->do_nmf != 0 ? true : false
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will make change to |
Fix #3003. The marshalled Boolean size from C# to C should be 1 byte, not 4. Also, the change from LIBMF is for supporting quiet option in new implicit-feedback MF.