2

C#文字列を暗号化することを想定しているC dll関数に渡すのに苦労しています。残念ながら、それは単に何もしません。関数を呼び出した後、文字列は同じままです。

C 関数:

    #include <stdio.h>
    #include <stdlib.h>
     extern "C"{ 
     __declspec(dllexport) void Encrypt( char *plainText,long height,long inputLength)
    {
        unsigned char *encryptedText=(unsigned char*)malloc(sizeof(plainText));
        unsigned char **cipherArray;


        cipherArray=(unsigned char**)malloc(height*sizeof(unsigned char *));
        for(long i=0; i<height; i++)
        {
            cipherArray[i]=(unsigned char*)malloc(inputLength*sizeof(char));
            for (long j=0; j<inputLength ; j++)
                cipherArray[i][j]='#';
        }






        bool addRow=true;
        long row=0;
        long column = 0;
        long arrayIterator = 0;
        while(arrayIterator<inputLength){
            cipherArray[row][column] = plainText[arrayIterator];

                    column++;
                    if(addRow)row++;
                    else row--;
                    if (row >= height)
                    {
                        row--;
                        row--;
                        addRow=false;
                    }
                    else if (row < 0)
                    {
                        row++;
                        row++;
                        addRow = true;
                    }
                    arrayIterator++;
        }



        long iterator=0;
        for (long i=0; i< height; i++)
            for(long j=0; j<inputLength;j++){
                if(cipherArray[i][j]!='#'){
                    encryptedText[iterator]=cipherArray[i][j];
                    iterator++;
                }
            }

        long j=0;
        while(j<inputLength){
            plainText[j]=encryptedText[j];
            printf("%c",encryptedText[j]);
            j++;
        }

        for(long i=0; i<height; i++)
            free(cipherArray[i]);
        free(cipherArray);
        cipherArray = NULL; 


    }

     }

C# クラスを含む:

    namespace RailFenceCipher
    {
        public class CCipher
        {
            [DllImport("Win32Project3.dll", EntryPoint = "Encrypt", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
            public static extern void Encrypt([MarshalAs(UnmanagedType.LPStr)] string plainText, long height, long inputLength);



        }
    }

そして関数を呼び出します:

     private void cipherC()
            {

                string plainText = this.fileInput;
                Console.WriteLine("=== C# test, using IntPtr and Marshal ===");
                CCipher.dllprint();
                CCipher.Encrypt(plainText, this.height, this.fileInput.Length);
                this.fileOutputC = plainText;
                Console.WriteLine("=== END ===");
           }

呼び出し後、plainText は変更されません。

4

1 に答える 1

2

これは予想されることです。データをマーシャリングしていますが、アウトではありません。これは、文字列型のパラメーターの動作です。ネイティブ コードからテキストをマーシャリングするには、StringBuilder を使用する必要があります。

また、C# の long は 64 ビットですが、C++ の long は 32 ビットです。ピンボークは次のようになります。

[DllImport("Win32Project3.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Ansi)]
public static extern void Encrypt(StringBuilder plainText,
    int height, int inputLength);

また、渡す StringBuilder インスタンスの容量が、返されるテキストに対して十分であることを確認する必要があります。

おそらく、より大きな問題は、C++ コードが壊れていることです。少なくとも、sizeof(plainText) を受け取る malloc 呼び出しを修正する必要があります。それはポインターのサイズです。バッファの長さ、inputLength を渡す必要があります。相互運用を試みる前に、まずそのコードをデバッグする必要があります。

于 2013-10-28T21:11:42.250 に答える