Re: am having a problem with pinvoke and StringBuilder[ ]
- From: "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx>
- Date: Tue, 29 Apr 2008 18:58:45 +0200
"LK" <lkant2000@xxxxxxxxx> wrote in message news:u0RgHEhqIHA.524@xxxxxxxxxxxxxxxxxxxxxxx
Hi,
From a C# program I need to access an existing DLL that enumerates the
boards detected via a hardware probe of the system. The function that
does the enumeration expects an int * where it stores the number of boards
detected and a char *** where it stores the name of each board detected.
Since the String class is immutable, I have used StringBuilder in my code
but this results in a NullPointerException. Just for testing, I replaced
StriingBuilder[] with String[] and the code worked just fine (i.e, no
NullPointerExceptions occured and all messages populated in
the String[] in managed code was correctly printed by the DLL).
I am wondering what I am doing wrong in my code. For reference, I am
enclosing my C# code and my sample DLL code
thank you for your help.
Laxmikant Rashinkar (LK)
Here is the C# code
---------------------
using System;
using System.Text;
using System.Runtime.InteropServices;
class CallDll
{
[DllImport("TestLib.dll")]
public static extern void AccessCheck();
[DllImport("TestLib.dll")]
public static extern int EnumerateBoards(ref int numBoards, ref StringBuilder[] boards);
public static void Main()
{
int numBoards = 0;
int maxBoards = 5;
int i;
StringBuilder[] boards = new StringBuilder[maxBoards];
for(i=0; i<maxBoards; i++)
boards[i] = new StringBuilder(100);
AccessCheck();
EnumerateBoards(ref numBoards, ref boards);
Console.WriteLine("Found " + numBoards + " boards\n");
for(i=0; i<numBoards; i++)
Console.WriteLine("" + boards[i] + "\n");
}
}
Here is the DLL code
----------------------
#include <stdio.h>
#include <string.h>
extern "C" __declspec(dllexport) void AccessCheck()
{
printf("Hello from TestLib.dll\n");
}
extern "C" __declspec(dllexport) int EnumerateBoards(int *numBoards, char ***boards)
{
char **cpp = *boards;
strcpy(cpp[0], "VGA");
strcpy(cpp[1], "NIC");
*numBoards = 2;
return 0;
}
Here is the output from my program:
------------------------------------
Hello from TestLib.dll
Unhandled Exception: System.NullReferenceException: Object reference not set
to an instance of an object.
at CallDll.EnumerateBoards(Int32& numBoards, StringBuilder[]& boards)
at CallDll.Main()
And here is how I compile my test code
----------------------------------------
@echo off
cl TestLib.cpp -LD -FeTestLib.dll
csc CallDll.cs
CallDll
Why the triple (***) indirection, a stringBuilder is passed as a pointer and a StringBuilder[] is passed as a pointer to a pointer?
...
extern "C" __declspec(dllexport) int EnumerateBoards(int *numBoards, char **boards)
{
char **cpp = boards;
...
Remove the ref from the DllImport declaration and the function call in your C# code and it should work.
....
public static extern int EnumerateBoards(ref int numBoards, StringBuilder[] boards);
EnumerateBoards(ref numBoards, boards);
Willy.
.
- Follow-Ups:
- References:
- Prev by Date: am having a problem with pinvoke and StringBuilder[ ]
- Next by Date: Re: am having a problem with pinvoke and StringBuilder[ ]
- Previous by thread: am having a problem with pinvoke and StringBuilder[ ]
- Next by thread: Re: am having a problem with pinvoke and StringBuilder[ ]
- Index(es):
Relevant Pages
|