Solved

c# to C++ - transfer an array of int*

Posted on 2004-10-12
10
303 Views
Last Modified: 2008-01-09
So I was in a hurry the other day and couldn't figure out the *right* way to do something.  Instead I ended up with this lovely funtion in my .cpp library:

int HoldEmLibrary::CompareSixHands(Deck handA,                                                   Deck handB,
                    Deck handC,
                    Deck handD,
                    Deck handE,
                    Deck board,
                   int *retCount,
                   int *retHandACount,
                   int *retHandBCount,
                   int *retHandCCount,
                   int *retHandDCount,
                   int *retHandECount,
                   int *retTieCount,
                   int *HandsA0,
                   int *HandsA1,
                   int *HandsA2,
                   int *HandsA3,
                   int *HandsA4,
                   int *HandsA5,
                   int *HandsA6,
                   int *HandsA7,
                   int *HandsA8,
                   int *HandsB0,
                   int *HandsB1,
                   int *HandsB2,
                   int *HandsB3,
                   int *HandsB4,
                   int *HandsB5,
                   int *HandsB6,
                   int *HandsB7,
                   int *HandsB8,
                   int *HandsC0,
                   int *HandsC1,
                  int *HandsC2,
                  int *HandsC3,
                  int *HandsC4,
                  int *HandsC5,
                  int *HandsC6,
                  int *HandsC7,
                  int *HandsC8,
                  int *HandsD0,
                  int *HandsD1,
                  int *HandsD2,
                  int *HandsD3,
                  int *HandsD4,
                  int *HandsD5,
                  int *HandsD6,
                  int *HandsD7,
                  int *HandsD8,
                  int *HandsE0,
                  int *HandsE1,
                  int *HandsE2,
                  int *HandsE3,
                  int *HandsE4,
                  int *HandsE5,
                  int *HandsE6,
                  int *HandsE7,
                  int *HandsE8
                  )

Which is called like this from an unsafe funtion in C#:

                  int* iHandsA = stackalloc int[9];
                  int* iHandsB = stackalloc int[9];

                  for (int icnt = 0; icnt <9; icnt++)
                  {
                        iHandsA[icnt] = 0;
                        iHandsB[icnt] = 0;
                  }

                  int iCount = lib.CompareTwoHands(d1,d2,d3,&iCnt,&iH1,&iH2,&iTie,
                        &(iHandsA[0]),&iHandsA[1],&iHandsA[2],&iHandsA[3],&iHandsA[4],&iHandsA[5],&iHandsA[6],&iHandsA[7],&iHandsA[8],
                        &(iHandsB[0]),&iHandsB[1],&iHandsB[2],&iHandsB[3],&iHandsB[4],&iHandsB[5],&iHandsB[6],&iHandsB[7],&iHandsB[8]);

-------------------------

Obviously this is fugly and leads to ugliness on both ends...but for the life of me, I couldn't figure out the right way to do it.  Help?

-Jon

0
Comment
Question by:mittelhauser
  • 6
  • 4
10 Comments
 

Author Comment

by:mittelhauser
ID: 12290574
I presume it is obvious but what I would prefer is to pass the various int* as arrays instead of indvidually.  
0
 
LVL 14

Accepted Solution

by:
AvonWyss earned 500 total points
ID: 12290796
Well, just pass them as arrays! The marshaller does support this, just use the MarshalAs-Attribute to specify what it is:

[DllImport ("SomeDll.dll")]
public static extern void ExternalMethodWithConstantSizedArray([MarshalAs(UnmanagedType.LPArray, SizeConst=3)] Vertex[] data);

or

[DllImport ("SomeDll.dll")]
public static extern void ExternalMethodWithVaribaleSizedArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Vertex[] data, long size);

That should do the trick...
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 12290821
Note that if you want to retrieve data from the external method, you can use the ref or out modifier and the In- and Out-Attributes. The marshaller then also copies data back from unmanaged space to managed space.
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:mittelhauser
ID: 12291146
I guess I need a more specific answer because I can't figure out how to apply that.

It has been awhile since I messed around with c++ but I needed to for this app.  Some more specifics, the C++ function is in managed code.  I need the C++ function to fill-in all of the ints which are passed.

Can you provide me an example declaration for both the C++ function and the C# call.  Just take a case where I want to pass some parameters (say 2 strings for the example) to a C++ function which uses those parameters to calculate 20 int values,  I need to get those 20 integers back to the C# function that called.  My current solution has the C# pass 20 int* but that is ugly and requires unsafe code...

-Jon
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 12291358
Have a look at this USENET discussion:
http://groups.google.com/groups?threadm=s5EBc.5342%2437.703686%40news.siol.net

I believe that this is what you are looking for.
0
 

Author Comment

by:mittelhauser
ID: 12291675
Well maybe but it doesn't seem like the solution given in the post actually works.  I get the following:

c:\code\poker\HoldEmLib\HoldEmLib.h(105): error C3162: 'int __gc *__gc * ' : __gc pointers to interior __gc pointers cannot be declared

when I try to declare a test function in the C++ lib:

void HoldEmLibrary::TestArrayPass(int __gc * __gc * pArray) like the example.

I just feel like I am making this too hard.  All I want to do is have a managed C++ function return a set of ints to a managed C# app...seems like a common thing to do...right?

0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 12291721
Er, why are you doing "int __gc * __gc * pArray"? You only need one __gc * - the one that points to the start of the array, right? And this you can then use as ref or out (when you apply the OutAttribute on the C++ code) in the C# part.
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 12291758
Here's the MSDN reference to the different __gc usages:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/vclrf__gc.asp

I'm sorry that I can't provide you with a working example, but I don't use C++ and have just been importing exported dll functions using the .NET marshaller so far, thus my first comment since I didn't realize you were talking of managed C++.
0
 

Author Comment

by:mittelhauser
ID: 12292155
Well I solved the problem by moving the C++ functions I needed into an unmanaged DLL and using the orginal suggestion.  Not really a true solution but it worked for me...I'll award you the points.
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 12292174
Thank you. As I said, I'm sorry, but I haven't used managed C++, so I don't really have a clue about your specific question with managed C++. But I'm glad it worked with unmanaged code.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question