question

AliGhorbanian-9052 avatar image
0 Votes"
AliGhorbanian-9052 asked JackJJun-MSFT commented

MarshalAs SAFEARRAY in C# .Net Core

I have C++ Dll function:


 __declspec(dllexport) int __stdcall GetData(SAFEARRAY** ppSafeArrayToModify) {
    
     IRecordInfoPtr pIRecInfs = NULL;
     SafeArrayGetRecordInfo(*ppSafeArrayToModify, &pIRecInfs);
     if (pIRecInfs == NULL)
     {
         return 2020;
     }
 }


I want use that Dll in C# .Net Core with down syntax:

 public static extern int GetData(
     [In]
     [Out]
     [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_RECORD)] 
     ref db_anneal_stack_csharp[] myStructArr);

But when run this code,I see this error.


{"Operation is not supported. (0x80131515)"}.


When I run this syntax in C#, Do Not have any error. Please help me. good luck.




dotnet-csharpc++
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@AliGhorbanian-9052, is any update? Please check if my answer works for you.

0 Votes 0 ·

1 Answer

JackJJun-MSFT avatar image
0 Votes"
JackJJun-MSFT answered

@AliGhorbanian-9052, based on my test, I can run the code successfully in a c# .net core(.net 5.0) console app.

Please check if you have done the following steps.

First, Please ensure that you set the C++/CLI properties like the following picture:

143617-image.png

Second, Please set the platform to x86 in your .net core console app.

143678-image.png

Third, Please make sure that you use the absolute path for the dll in the dllimport code.

  [DllImport(@"D:\projectname\Debug\NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
  private static extern void GetResult([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] ref int[] ar);

Finally, I provide a completed code example so that you can have a check.

C++:

 #include "pch.h"
 #include <comdef.h>
    
 // When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
    
 extern "C" __declspec(dllexport) void GetResult(SAFEARRAY * &data)
 {
     if (data != NULL)
     {
         // Begin print content of SAFEARRAY
         VARTYPE vt;
         HRESULT hr = SafeArrayGetVartype(data, &vt);
         if (SUCCEEDED(hr))
         {
             // To make this code simple, we print only
             // SAFEARRAY(VT_I4)
             if (vt == VT_I4)
             {
                 int* pVals;
                 hr = SafeArrayAccessData(data, (void**)&pVals); // direct access to SA memory
                 if (SUCCEEDED(hr))
                 {
                     long lowerBound, upperBound;  // get array bounds
                     SafeArrayGetLBound(data, 1, &lowerBound);
                     SafeArrayGetUBound(data, 1, &upperBound);
                     long cnt_elements = upperBound - lowerBound + 1;
                     for (int i = 0; i < cnt_elements; i++)  // iterate through returned values
                     {
                         int val = pVals[i];
                         printf("C++: %d\n", val);
                     }
                     SafeArrayUnaccessData(data);
                 }
                 else
                 {
                     // Error
                 }
             }
         }
         else
         {
             // Error
         }
         // End print content of SAFEARRAY
         // Delete the SAFEARRAY if already present
         SafeArrayDestroy(data);
         data = NULL;
     }
     {
         // Creation of a new SAFEARRAY
         SAFEARRAYBOUND bounds;
         bounds.lLbound = 0;
         bounds.cElements = 10;
         data = SafeArrayCreate(VT_I4, 1, &bounds);
         int* pVals;
         HRESULT hr = SafeArrayAccessData(data, (void**)&pVals); // direct access to SA memory
         if (SUCCEEDED(hr))
         {
             for (ULONG i = 0; i < bounds.cElements; i++)
             {
                 pVals[i] = i + 100;
             }
         }
         else
         {
             // Error
         }
     }
 }

C#:


 [DllImport(@"D:\ProjectName\Debug\NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
         private static extern void GetResult([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)] ref int[] ar);
         static void Main(string[] args)
         {
             var data = new int[] { 1, 2, 3, 4, 5 };
             GetResult(ref data);
             if (data != null)
             {
                 for (int i = 0; i < data.Length; i++)
                 {
                     Console.WriteLine("C#: {0}", data[i]);
                 }
             }
             else
             {
                 Console.WriteLine("C#: data is null");
             }
             Console.ReadKey();
         }

Tested result:


143618-image.png







If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.





image.png (54.2 KiB)
image.png (12.6 KiB)
image.png (3.7 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.