Add C code to my C# application?

C

cyberco

I'm developing for Windows Mobile 2005 PPC using Visual Studio 2005.

I need to invoke methods on a DLL (Iphlpapi.dll) but I can't get this
working from C# using p/invoke so I want to write some C code that
invokes the DLL. Similar to this:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/getipforwardtable.asp

Now how can I, in Visual Studio 2005, create and use such a C class ?
Do I have to create an 'MFC Smart Device DLL' project? If so, how do I
combine it with my C# project?
 
B

Ben Voigt

cyberco said:
I'm developing for Windows Mobile 2005 PPC using Visual Studio 2005.

I need to invoke methods on a DLL (Iphlpapi.dll) but I can't get this
working from C# using p/invoke so I want to write some C code that
invokes the DLL. Similar to this:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/getipforwardtable.asp

Now how can I, in Visual Studio 2005, create and use such a C class ?
Do I have to create an 'MFC Smart Device DLL' project? If so, how do I
combine it with my C# project?
Try a New Project->Visual C++->CLR->Class Library. Then, from the C#
project references, choose Projects, and then the name of the C++ project.
 
T

Tom Porterfield

cyberco said:
I'm developing for Windows Mobile 2005 PPC using Visual Studio 2005.

I need to invoke methods on a DLL (Iphlpapi.dll) but I can't get this
working from C# using p/invoke so I want to write some C code that
invokes the DLL. Similar to this:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/getipforwardtable.asp

Now how can I, in Visual Studio 2005, create and use such a C class ?
Do I have to create an 'MFC Smart Device DLL' project? If so, how do I
combine it with my C# project?

See if this article helps -
http://bertjansen.spaces.live.com/Blog/cns!D9B33D4A940B6FFD!192.entry.
 
W

WebSnozz

I actually am having trouble with a similar issue. In order to
reference the DLL project the way just described, the C++ has to be in
cpp files and compiled with the /clr switch. Otherwise you get some
sort of "can't link with native dll" error with /clr, and without /clr
you can't compile as c code, you have to use *.cpp files compiled as
c++. This difference isn't significant unless you are doing really low
level stuff with your C that is not exceptable by the C++ compiler.

I think you can use native C dll's without the source code I believe,
and without referencing the project. There is an Import attribute that
you can use in C#. I don't think it is compile time safe though, as I
recall that you must give it the name of the DLL and functions you
intend to call. I haven't quite grasped how it makes sure all the
function calls into the DLL are passing the correct type of parameters.
I plan to read up on that more. Sorry I've not been more help.
 
B

Ben Voigt

I think you can use native C dll's without the source code I believe,
and without referencing the project. There is an Import attribute that
you can use in C#. I don't think it is compile time safe though, as I
recall that you must give it the name of the DLL and functions you
intend to call. I haven't quite grasped how it makes sure all the
function calls into the DLL are passing the correct type of parameters.
I plan to read up on that more. Sorry I've not been more help.
The OP said he already tried p/invoke and it wasn't working out. Certainly
it's a lot easier to use the C++ compiler, because it understands the
original header file directly.

www.pinvoke.net is a good place to get the DllImport definitions so you
don't have to make them yourself.
 
C

cyberco

Try a New Project->Visual C++->CLR->Class Library. Then, from the C#
project references, choose Projects, and then the name of the C++ project.

This unfortunately doesn't work for device projects, I get the error:
"A reference to 'projectx' could not be added because it is not a
device project".
Is there no way to just compile the C++ code, create a dll and use that
in the C# project?
 
C

cyberco

I'm a newbie when it comes to creating C++ applications (for Windows
Mobile) using Visual Studio 2005. Now I'm stuck trying to invoke an
existing DLL (Iphlpapi.dll, which is a common DLL on windows) from my
own C++ class which in turn is invoked from C#: Schematic:
 
M

mostly_magic

You need to include the iphlpapi.lib library file in your project.
This file defines the prototypes for the visible methods within the
dll. Then you can call the method directly from your code.
 
C

cyberco

Oh boy...I am still struggling with this.
Now I'm at the stage that I created a WIN32 project in my solution, and
created the C++ file below. The code from the 'createIpForwardEntry()'
method is from an online example that I found. The code compiles, but
it doesn't create a DLL or so, so I wouldn't know how to invoke this
DLL and test it.
Still, I really wonder what I'm doing wrong when invoking iphlpapi.dll
directly from C# as discussed here:
http://groups-beta.google.com/group...72c61c3b22b/369e27fc9415d06e#369e27fc9415d06e
There must be others that have tried this...
What are the other places to search for info on these matters?

====== C++ FILE =======
#include "stdafx.h"

#ifdef _MANAGED
#pragma managed(push, off)
#endif
#ifdef __cplusplus
extern "C" {
#endif

typedef DWORD (*getIpForwardTableFunction)(PMIB_IPFORWARDTABLE, PULONG,
BOOL);
typedef DWORD (*createIpForwardEntryFunction)(PMIB_IPFORWARDROW);
typedef DWORD (*setIpForwardEntryFunction)(PMIB_IPFORWARDROW);
typedef DWORD (*deleteIpForwardEntryFunction)(PMIB_IPFORWARDROW);

HINSTANCE hinstLib;
getIpForwardTableFunction myGetIpForwardTable = NULL;
createIpForwardEntryFunction myCreateIpForwardEntry = NULL;
setIpForwardEntryFunction mySetIpForwardEntry = NULL;
deleteIpForwardEntryFunction myDeleteIpForwardEntry = NULL;

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
LPCWSTR dllName = LPCWSTR("Iphlpapi.dll");
hinstLib = LoadLibrary(dllName);
if (hinstLib == NULL) {
printf("Error: could not load Iphlpapi.dll\n");
return FALSE;
}

myGetIpForwardTable = (getIpForwardTableFunction)
GetProcAddress(hinstLib, "GetIpForwardTable");
if (myGetIpForwardTable == NULL) {
printf("Error: could not find function getipforwardtable");
return FALSE;
}

myCreateIpForwardEntry = (createIpForwardEntryFunction)
GetProcAddress(hinstLib, "CreateIpForwardEntry");
if (myCreateIpForwardEntry == NULL) {
printf("Error: could not find function createipforwardentry");
return FALSE;
}

mySetIpForwardEntry = (setIpForwardEntryFunction)
GetProcAddress(hinstLib, "SetIpForwardEntry");
if (mySetIpForwardEntry == NULL) {
printf("Error: could not find function setipforwardentry");
return FALSE;
}

myDeleteIpForwardEntry = (deleteIpForwardEntryFunction)
GetProcAddress(hinstLib, "DeleteIpForwardEntry");
if (myDeleteIpForwardEntry == NULL) {
printf("Error: could not find function deleteipforwardentry");
return FALSE;
}

return TRUE;
}

__declspec(dllexport) void __stdcall createIpForwardEntry() {
PMIB_IPFORWARDTABLE pIpForwardTable = NULL;
PMIB_IPFORWARDROW pRow = NULL;
DWORD dwSize = 0;
BOOL bOrder = FALSE;
DWORD dwStatus = 0;
DWORD NewGateway = 0xDDBBCCAA; // this is in host order Ip Address
AA.BB.CC.DD is DDCCBBAA

// Find out how big our buffer needs to be.
dwStatus = myGetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
if (dwStatus == ERROR_INSUFFICIENT_BUFFER) {
// Allocate the memory for the table
if (!(pIpForwardTable = (PMIB_IPFORWARDTABLE)malloc(dwSize))) {
printf("Malloc failed. Out of memory.\n");
exit(1);
}
// Now get the table.
dwStatus = myGetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
}

if (dwStatus != ERROR_SUCCESS) {
printf("getIpForwardTable failed.\n");
if (pIpForwardTable)
free(pIpForwardTable);
exit(1);
}

// Search for the row in the table we want. The default gateway has a
destination
// of 0.0.0.0. Notice that we continue looking through the table, but
copy only
// one row. This is so that if there happen to be multiple default
gateways, we can
// be sure to delete them all.
for (unsigned long int i=0; i < pIpForwardTable->dwNumEntries; i++) {
if (pIpForwardTable->table.dwForwardDest == 0) {
// We have found the default gateway.
if (!pRow) {
// Allocate some memory to store the row in; this is easier than
filling
// in the row structure ourselves, and we can be sure we change
only the
// gateway address.
pRow = (PMIB_IPFORWARDROW)malloc(sizeof(MIB_IPFORWARDROW));
if (!pRow) {
printf("Malloc failed. Out of memory.\n");
exit(1);
}
// Copy the row
memcpy(pRow, &(pIpForwardTable->table),
sizeof(MIB_IPFORWARDROW));
}

// Delete the old default gateway entry.
dwStatus = myDeleteIpForwardEntry(&(pIpForwardTable->table));

if (dwStatus != ERROR_SUCCESS) {
printf("Could not delete old gateway\n");
exit(1);
}
}
}

// Set the nexthop field to our new gateway - all the other properties
of the route will
// be the same as they were previously.
pRow->dwForwardNextHop = NewGateway;

// Create a new route entry for the default gateway.
dwStatus = myCreateIpForwardEntry(pRow);

if (dwStatus == NO_ERROR)
printf("Gateway changed successfully\n");
else if (dwStatus == ERROR_INVALID_PARAMETER)
printf("Invalid parameter.\n");
else
printf("Error: %d\n", dwStatus);

// Free resources
if (pIpForwardTable)
free(pIpForwardTable);
if (pRow)
free(pRow);
}


#ifdef __cplusplus
}
#endif

#ifdef _MANAGED
#pragma managed(pop)
#endif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top