Reputation: 387
I'm tyring to pass a C# string to C dll function which supposes to encrypt it. Unfortunately, it does simply nothing. After calling the function, the string is still the same.
C function:
#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;
}
}
Containing C# class:
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);
}
}
and calling for the function:
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 ===");
}
after the calling, plainText is not changed.
Upvotes: 2
Views: 657
Reputation: 613013
This is to be expected. You are marshalling the data in, but not out. That is the behaviour for a parameter of type string. You need to use StringBuilder in order to marshal text back from the native code.
In addition, C# long is 64 bit, but C++ long in 32 bit. Your pinvoke should be:
[DllImport("Win32Project3.dll", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
public static extern void Encrypt(StringBuilder plainText,
int height, int inputLength);
And you need to make sure that the capacity of the StringBuilder instance that you pass is sufficient for the text to be returned.
Perhaps a bigger problem is that your C++ code is broken. At the least, you need to fix the malloc call which receives sizeof(plainText). That's the size of a pointer. You need to pass the length of the buffer, inputLength. You should debug that code first before attempting interop.
Upvotes: 2