Luca,
>i've a C++ dll with a function that return a pointer to a struct, and i need to
>call that function from a C# windows app.
[...]
>// function prototype
>extern "C" __declspec(dllexport) void Netlink_Read_NKAF(NKAF*);
There's no way the function can return a pointer since the only
parameter is passed by value, and the function has a void return type.
I'll assume that the function simply populates the fields of the
existing struct you pass in.
>// C++ Code
>
[quoted text clipped - 5 lines]
> char* TaxNumber;
>};
[...]
>// C# code
>[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
[quoted text clipped - 5 lines]
>[MarshalAs(UnmanagedType.ByValTStr,SizeConst=16)] string TaxNumber;
>}
Since the strings in the C++ declaration aren't fixed-size, you should
remove the MarshalAs attirbutes in the C# declaration.
>[DllImport("scgx.dll")]
>public static extern void Netlink_Read_NKAF(IntPtr FreeData);
Not sure why you chose IntPtr as the parameter type. It would be much
easier with
public static extern void Netlink_Read_NKAF(ref NKAF FreeData);
Mattias

Signature
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Luca Beretta - 04 Oct 2005 16:40 GMT
Mattias,
first thanks you a lot for your answer; then, my function in C++ dll do
following things:
extern "C" __declspec(dllexport) void Netlink_Read_NKAF(NKAF *FreeData)
{
NKAF ret;
/* initialize structure */
ret.Address = '\0';
ret.AgencyCode = '\0';
ret.BirthDate = '\0';
// populate all the fields reading a smartcard (sample)
ret.DoctorCode = new char[dwSubSub84L];
for(DWORD idx = 0; idx < dwSubSub84L; idx++)
{
ret.DoctorCode[idx] = (BYTE)NKAF_Stream_Data[jdx+idx+1];
}
ret.DoctorCode[idx] = '\0';
FreeData = &ret;
}
in my original dll i've a different function prototype, that receive no
parameters and return directly the pointer, but i've some problem in the
interop with C#, so reading MSDN i founded some samples like mine actual
version.
i need to change my c++ code ? which is the best way ?
now i changed my C# code to use ref like this:
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
public struct NKAF
{
string SectorCode;
string CountryCode;
string AgencyCode;
}
[DllImport("scgx.dll")]
public static extern void Netlink_Read_NKAF(ref NKAF FreeData);
NKAF dati = new NKAF();
Netlink_Read_NKAF(ref dati);
but i get a System.NullReferenceException
> Luca,
>
[quoted text clipped - 42 lines]
>
> Mattias
Mattias Sjögren - 07 Oct 2005 23:11 GMT
Luca,
>extern "C" __declspec(dllexport) void Netlink_Read_NKAF(NKAF *FreeData)
[...]
> FreeData = &ret;
>}
This wont work. You're only changing the local pointer value of the
argument, not what it points to. So no changes will propagate back to
the caller.
Instead of populating a new NKAF struct(ret) in the function code, you
could modify the existing one:
FreeData->Address = '\0';
and so on. But you may have to change the C# declarations to use
IntPtr instead of string if you chose to do it this way.
Also if you return pointers to buffers allocated with new, like in
ret.DoctorCode = new char[dwSubSub84L];
you have to provide a way for the caller to free that memory.
Mattias

Signature
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.