0

From the C code this is the structure which is part of another structure:

struct loop_funcs {
  size_t (*loop_convert) (iconv_t icd,
                          const char* * inbuf, size_t *inbytesleft,
                          char* * outbuf, size_t *outbytesleft);
  size_t (*loop_reset) (iconv_t icd,
                        char* * outbuf, size_t *outbytesleft);
};

So far I have this defined in C# to use this structure:

        [StructLayout(LayoutKind.Sequential)]
        struct loop_funcs {
            ulong (loop_convert) (conv_struct icd,
                          string * inbuf, ulong inbytesleft,
                          string * outbuf, ulong outbytesleft)
            ulong (loop_reset) (conv_struct icd,
                       char* * outbuf, ulong outbytesleft)
        }

However I am lost on how to handle this conversion it is not a simple structure definition that I have found so far in other examples.

Richard Wheeler
  • 618
  • 2
  • 8
  • 21
  • Is the question about what the C struct means, or about how to write a C# analogue? (Or both?) – John Bollinger Apr 26 '19 at 17:46
  • In C# you need to create a *class* (I don't know the syntax by heart, so, consult with documentation) and provide public methods. The languages have different paradigms, there is no 1:1 way to translate the code. – 0andriy Apr 26 '19 at 17:53
  • Both if possible. I know the *variable means differencing a pointer. size_t is a unsigned integer. The (*loop_) (...) I don't understand in the context of a structure. – Richard Wheeler Apr 26 '19 at 17:55
  • I know C# very well and C from a long time ago. – Richard Wheeler Apr 26 '19 at 17:56
  • Why don't you describe your structure in plain english and what the idea is behind it? You can have structs, lists of structs, list of lists, lots of possibilities – Alex M Apr 26 '19 at 17:57
  • Sorry I don't control the C code it is from the library called libiconv which I was able to compile on Windows. Now I need C# to call the exported functions. The calls use pointers to these structures. – Richard Wheeler Apr 26 '19 at 17:58
  • On a side note, why do you need to use the `libiconv` library, when C# understands Unicode perfectly well? – Mark Benningfield Apr 26 '19 at 18:20
  • Well we have an issue where the process to generate XML ends up with double encoding text with Unicode values in it. I found that if I ran the iconv program it would detect that and fix it. I did try fixing it just using just C# but I don't understand the logic used to remove the double-encoding. – Richard Wheeler Apr 26 '19 at 18:59
  • It might be faster to figure out your XML encoding issues than devising an interop wrapper for `libiconv`, if you are not *very* familiar with C. – Mark Benningfield Apr 26 '19 at 21:32
  • Spent several days on that, it is caused by the command line interface of standard out that the vendor forces us to use to get the data. Basically it is very, very difficult to have standard out conform to Unicode output in a Windows environment. – Richard Wheeler Apr 29 '19 at 12:29
  • It was this link that let me to try and use iconv: https://stackoverflow.com/questions/15694283/utf8-not-showing-hyphens-correctly-in-echoed-text – Richard Wheeler Apr 29 '19 at 12:44

1 Answers1

1

Without knowing more details about your specific interop strategy, it's difficult to be precise, but this is a common-case example of function-pointer marshaling.

  // need a static class to contain the definitions of the managed
  // equivalent of function pointers, which are delegates
  static class Native
  {
    // assuming you are using these as callbacks, the Marshaler needs to know
    // how to fix up the call stack
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate ulong LoopConvertFunc([MarshalAs(UnmanagedType.Struct)]conv_struct icd,
                                          ref StringBuilder inbuf,
                                          ref ulong inbytesLeft,
                                          ref StringBuilder outbuf,
                                          ref ulong outbytesLeft);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate ulong LoopResetFunc([MarshalAs(UnmanagedType.Struct)]conv_struct icd, ref StringBuilder outbuf, ref ulong outbytesLeft);
  }

  [StructLayout(LayoutKind.Sequential)]
  struct loop_funcs
  {
    Native.LoopConvertFunc loop_convert;
    Native.LoopResetFunc loop_reset;
  }

The function pointers have to be defined as delegates, and the marshaler has to know how to fix up the call stack, so you use the UnmanagedFunctionPointer attribute.

Further, depending on the actual use-case, a StringBuilder is usually used to marshal a writable string buffer, using the ref keyword.

Mark Benningfield
  • 2,800
  • 9
  • 31
  • 31
  • Ok, so the ```size_t (*loop_convert) (iconv_t icd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);``` is a function in the C code. I thought it might but wasn't real sure. I will test this and see if it works. – Richard Wheeler Apr 26 '19 at 18:11
  • If it doesn't work, you are going to have to post *much more specific* interop requirements, like documentation of the use of the native structs and member functions, how you are trying to call it and what you are expecting the result to be. – Mark Benningfield Apr 26 '19 at 18:16
  • 1
    Trying to write a C# wrapper around the 3 functions from the library libiconv – Richard Wheeler Apr 26 '19 at 18:23
  • I used this https://github.com/yuryleb/iconv-for-windows/tree/master/libiconv to generate the Windows version. The 3 functions are: ```iconv_t iconv_open(const char *tocode, const char *fromcode);```, ```size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);```, ```int iconv_close (iconv_t cd);``` – Richard Wheeler Apr 26 '19 at 18:30