Solved

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

Posted on 2004-10-12
10
291 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
 

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
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

746 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now