Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved]Transform... a class? or maybe an struct?  (Read 16712 times)

0 Members and 3 Guests are viewing this topic.

Inverness

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Transform... a class? or maybe an struct?
« Reply #30 on: May 19, 2012, 09:59:48 am »
I know how it works, I already do that with other structures ;)

But CSFML is a binding too, so there's no Transform structure in it, only a wrapper around a C++ sf::Transform pointer. So I would have to do the same modification in CSFML, which means duplicating the Transform functions three times. Definitely not the best thing to maintain.
Well, part of the problem seems to be that you have this C binding in-between C# and C++ and I don't know what exactly it's doing which is making things difficult to brainstorm about.

My main ports are that:
1. Transform needs to be a struct.
2. Transform methods should be defined in C# and modify transforms by reference.
3. Transform instances should be sent to C++ by pointer to the C# struct which matches the layout of the C++ struct.
4. Transform instances retrieved from C++ should be copied into a C# struct, not wrapped.

Perhaps you should simply eliminate the C binding in-between and import the functions from the C++ modules directly. You can avoid use of extern "C" too by importing the decorated function names. Making sure that the decorated function names are up to date in the C# binding seems simpler than what we're going through now.

Edit: I just reread your post, and I'm wondering why you think you'd need to do the same modification in CSFML. If the C# struct has the same layout you need only cast that to the wrapper you're using in CSFML and pass that to wherever it needs to be. CSFML shouldn't be able to tell the difference.

Looking at your code, you have:

struct sfTransform
{
    sf::Transform This;
};

You just need to pass a C# struct to whatever CSFML functions take a sfTransform* and it should work fine, no? Marshal.PtrToStructure() should help here for copying pointers you get from C/C++ into a new C# struct.
« Last Edit: May 20, 2012, 01:03:25 pm by Inverness »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Transform... a class? or maybe an struct?
« Reply #31 on: May 22, 2012, 06:00:56 pm »
Problem solved. The only thing that I still don't like is that the default constructor cannot produce an identity transform.
// this is *not* correct
Transform t = new Transform();
t.translate(10, 20);

// this is correct
Transform t = Transform.Identity;
t.translate(10, 20);
Is there something I can do?

Quote
Perhaps you should simply eliminate the C binding in-between and import the functions from the C++ modules directly. You can avoid use of extern "C" too by importing the decorated function names. Making sure that the decorated function names are up to date in the C# binding seems simpler than what we're going through now.
Decorated function names are specific to each compiler. This means that CSFML could be compiled by only a single compiler; this could be ok for Windows since I distribute the compiled CSFML files, but how am I supposed to handle OS X and Linux?

Quote
Looking at your code, you have:

struct sfTransform
{
    sf::Transform This;
};

You just need to pass a C# struct to whatever CSFML functions take a sfTransform* and it should work fine, no?
No, it is more tricky because of memory management and object lifetime. It would be complicated to explain and I'm in a hurry this evening, sorry :)
Laurent Gomila - SFML developer

Silvah

  • Guest
Re: Transform... a class? or maybe an struct?
« Reply #32 on: May 22, 2012, 07:55:54 pm »
Perhaps you should simply eliminate the C binding in-between and import the functions from the C++ modules directly. You can avoid use of extern "C" too by importing the decorated function names. Making sure that the decorated function names are up to date in the C# binding seems simpler than what we're going through now.
Please don't. C ABI is a de facto standard on given platform, it's the same on all or almost all compilers there. C++ ABI tends to vary widely even between different version of the same compiler. Do you want SFML to become an unmaintainable mess? Or you want it to work only with some very specific compiler on a very specific platform? Or you want it to be usable only from C++?

NinjaFighter

  • Jr. Member
  • **
  • Posts: 91
    • View Profile
    • http://www.sebagames.wordpress.com
Re: Transform... a class? or maybe an struct?
« Reply #33 on: May 22, 2012, 08:20:31 pm »
Thanks Laurent!  ;D

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #34 on: May 22, 2012, 11:41:40 pm »
Quote
Thanks Laurent!
Any idea about the default constructor problem? How does XNA matrices handle this?
Laurent Gomila - SFML developer

NinjaFighter

  • Jr. Member
  • **
  • Posts: 91
    • View Profile
    • http://www.sebagames.wordpress.com
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #35 on: May 23, 2012, 02:28:43 am »
Yeah, the XNA matrices do not contains any reference value inside.. so, instead of use an array of floats, these structs have various members.

instead of do:
public struct Matrix
{
   public float[] Values {get; private set;}
}
 

they write:
public struct Matrix
{
   public float M11 {get;set;}
   public float M12 {get;set;}
   public float M13 {get;set;}
   public float M14 {get;set;}
   public float M21 {get;set;}
   public float M22 {get;set;}
   //TODO: Add other values up to M44
}
 

take a look here: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.matrix_members
« Last Edit: May 23, 2012, 05:51:11 am by NinjaFighter »

Inverness

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Transform... a class? or maybe an struct?
« Reply #36 on: May 23, 2012, 04:06:35 am »
No, it is more tricky because of memory management and object lifetime. It would be complicated to explain and I'm in a hurry this evening, sorry :)
Well I'm saying you copy the struct in those instances to avoid having any issues. But if you're marshalling a reference in C#, then the object should stay alive since its on the stack so it will work with C++ functions that are taking the struct by reference, and copies should also work.

Is there something I can do?
No, not really. It's a rule of C# to not allow structs to have default constructors so allocation and other things work just fine by zeroing the memory. I don't really see it as a problem myself.

Anyhow, thanks for the change. I really appreciate it.
« Last Edit: May 23, 2012, 05:51:55 am by Inverness »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #37 on: May 23, 2012, 08:09:23 am »
Quote
Yeah, the XNA matrices do not contains any reference value inside.. so, instead of use an array of floats, these structs have various members.
That's what I do too, but how does that solve the default constructor problem?

Quote
No, not really. It's a rule of C# to not allow structs to have default constructors so allocation and other things work just fine by zeroing the memory. I don't really see it as a problem myself.
The first time that I tested the new code, it failed because I wrote "t = new Transform()" instead of "t = Transform.Identity". So to me this is clearly a problem. How many users will do the same mistake?
Laurent Gomila - SFML developer

NinjaFighter

  • Jr. Member
  • **
  • Posts: 91
    • View Profile
    • http://www.sebagames.wordpress.com
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #38 on: May 23, 2012, 08:53:39 am »
I figure what you say, because, there's no way to have a Matrix Identity by default, because the values must contains 1f at 0,0 | 1,1 | 2,2 etc. :-\
Until a few hours, I thought that Identity have all 0f  :P
I suppose, they can have a private bool member "IsInitialized" that could be used to validate before any transformation, "if (!matrix.IsInitalized) matrix = Matrix.Identity;", this could solve the problem, but is a little nasty.  :-\

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #39 on: May 23, 2012, 09:07:12 am »
Quote
I suppose, they can have a private bool member "IsInitialized" that could be used to validate before any transformation, "if (!matrix.IsInitalized) matrix = Matrix.Identity;", this could solve the problem, but is a little nasty.
I can't even do that: Transform must match the layout of the corresponding C structure, which means no additional member.
Laurent Gomila - SFML developer

NinjaFighter

  • Jr. Member
  • **
  • Posts: 91
    • View Profile
    • http://www.sebagames.wordpress.com
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #40 on: May 23, 2012, 09:24:53 am »
In that case, looks like you are between the sword and the wall.  :P
Anyway, XNA isn't a binding, so, they can handle these problems more easily, but, I think is ok to initialize a Transform with a static property.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #41 on: May 23, 2012, 09:43:04 am »
Quote
Anyway, XNA isn't a binding, so, they can handle these problems more easily
I looked at the online doc and saw how they handle this problem. Useful matrix can only be created by static functions, you can't rotate or translate an existing matrix, you can only multiply it with a new rotation or translation matrix and get a new one. So the default construction problem is less likely to happen with such a design.
Laurent Gomila - SFML developer

Inverness

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #42 on: May 31, 2012, 07:59:40 pm »
Now that I finally have time to get back to programming, I looked over the new Transform.cs, and I see you still have several imports for matrix mutations. This isn't really a priority, but I recommend you implement these operations in C# so they can be optimized by the JIT compiler instead of having to go through the overhead of marshalling to call a C function.

Also, Laurent, you don't always have to create a new matrix with XNA. The operations are overloaded so you can optionally specify an existing matrix as an out parameter to avoid making a new one.
« Last Edit: May 31, 2012, 08:11:17 pm by Inverness »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: [Solved]Transform... a class? or maybe an struct?
« Reply #43 on: May 31, 2012, 09:39:07 pm »
Quote
This isn't really a priority, but I recommend you implement these operations in C# so they can be optimized by the JIT compiler instead of having to go through the overhead of marshalling to call a C function.
My goal is not to duplicate SFML's code in every binding. Every function of the API involves a call to the C API, and as far as I know, there's no problem with that. If you want me to modify something, first prove that it's worth it.
Laurent Gomila - SFML developer