I have to replace an existing dll call that is registered and called using RegFn and CallFn respectively.
I am trying to write the dll using C# in the hope that as long as the function signature match and the dll is in the right place it will work.
so
pnHndl= RegFn("CALCULATE", "I", "I", "AJons.DLL")
pnRetVal = CallFn(pnHndl, 0)
My code is as follows:
[Guid("EAB7C2CD-2471-4BDA-90E9-F70403BAA557")]
[ComVisible(true)]
public class AJons : _AJons
{
[ComVisible(true)]
public int CALCULATE(int value)
{
return value * 2;
}
}
Foxpro doesn't play ball I just get 'could not load library AJon.dll'
Does anyone have any experience here?
Cheers.
From what I can see, those really old RegFn and CallFn are for calling Win32 native Dlls - completely different from COM.
What you need to create a Win32 dll that will work with those functions is C++.
What you should do (if you HAVE to keep using FoxPro) is at least use the latest version of VFP.
written on my iPhone
Update 1
1) Just in case I wasn't clear, you cannot make this kind of DLL from .NET.
2) Have a look at this link here for a very simple example of how to write a Win32 dll.
Related
Recently I have been trying to get some Point Cloud Library functionality going in my .NET framework application, and considering that there is no completely functional wrapper for PCL for C#, I made my own for a few functions as a test. Something like this:
[DllImport(DllFilePath, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr StatisticalOutlierFilter(IntPtr data, int length, int meanK = 50, float mulThresh = 1.0f);
Which calls a function from a C++ library, such as this:
EXPORT VectorXYZ* StatisticalOutlierFilter(VectorXYZ* data, int length, int meanK, float mulThresh) {
auto processedCloud = process.StatisticalOutlierFilter(data, length, meanK, mulThresh);
auto processedVector = convert.ToVectorXYZ(processedCloud);
return processedVector;
}
Where EXPORT is defined such for gcc:
#define EXPORT extern "C" __attribute__ ((visibility ("default")))
And relevant processing function from PCL is implemented such in a class (note that the returned is a boost shared pointer):
PointCloud<PointXYZ>::Ptr Processors::StatisticalOutlierFilter(VectorXYZ* data, int length, int meanK, float mulThresh) {
auto cloud = PrepareCloud(data, length);
PointCloud<PointXYZ>::Ptr cloud_filtered(new PointCloud<PointXYZ>);
StatisticalOutlierRemoval<PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(meanK);
sor.setStddevMulThresh(mulThresh);
sor.filter(*cloud_filtered);
return cloud_filtered;
}
This procedure works well with a dll built w/MSVC and running the whole thing on Windows, though the final target is gcc/Linux/Mono, where I get several errors of the following type (this is from mono debug):
'libavpcl_dll.so': '/usr/lib/libavpcl_dll.so: undefined symbol: _ZN3pcl7PCLBaseINS_8PointXYZEE13setInputCloudERKN5boost10shared_ptrIKNS_10PointCloudIS1_EEEE'.
I have investigated quite a bit so far, and have set my CmakeLists.txt to set(CMAKE_CXX_VISIBILITY_PRESET hidden) , therefore, I imagine, only functions I defined as EXPORT should be visible and imported - however, that is not the case, and I get the aforementioned errors. PCL was installed on Windows via vcpkg and on Xubuntu via apt. I am somewhat stumped as to what is the error source, considering the code runs well on windows, and builds without issue on Linux. Thanks.
I've been running into the same issue as you. I solved it by adding each reference library into the CMakeLists.txt file (I was missing the reference files which gave me the similar missing symbol issues).
I'm at the 'I don't know why this worked' stage but I can give you step by step implementation (I'm also trying to use DllImport into .NET on Linux).
Started with this:
https://medium.com/#xaviergeerinck/how-to-bind-c-code-with-dotnet-core-157a121c0aa6
Then added my in-scope files thanks to the main comment here: How to create a shared library with cmake?:
add_library(mylib SHARED
sources/animation.cpp
sources/buffers.cpp
[...]
)
run cmake .
run make -j$(grep -c ^processor /proc/cpuinfo)
copy path to .so file
DllImport path from above to my c# app
I've been requested to create a .Net dll for an old delphi program. I'm trying to do this with a COM Callable Wrapper, but I keep getting an error when it tries to load the dll (pretty general, something like "I couldn't load the dll"). Here is what the technical documentation says:
The DLL only needs to export one function under the name 'AUTHORIZE'.
function Authorize(InXml: PChar): PChar; stdcall;
(Delphi syntax. May be different in other languages.)
Here is my code for the CCW:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ComCallableWrapper
{
[Guid("C3FD922A-FB44-47B1-9C0C-8F7FAF57098B")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAuthorizer
{
[DispId(1)]
string Authorize(string lnpInXml);
}
[ProgId("ComCallableWrapper.Authorizer")]
[ClassInterface(ClassInterfaceType.None)]
public class Authorizer : IAuthorizer
{
public Authorizer()
{
}
public string Authorize(string lnpInXml)
{
return "Approved!";
}
}
}
I also run this command "regasm /tlb:ComCallableWrapper.tlb ComCallableWrapper.dll /codebase" on the computer where the delphi program is running.
I've been doing some research on google about how delphi invokes functions on a dll, and I found at least 2 ways:
function Authorize(lnpInXml: pchar): pchar; stdcall; external 'DLLName.dll';
and
oleObject := CreateOleObject('ComCallableWrapper.Authorizer');
ShowMessage(oleObject.Authorize('Approved?'));
It looks like COM works a little bit different. Is there a way to change my CCW to work like the first way?
Regards.
You con't need COM. And indeed using COM is a mistake because the Delphi program is not looking for a COM DLL.
What you need to do is to export an unmanaged function from your managed C# DLL. That's a little tricky and is in fact not supported. These are your most attractive options:
Use Robert Giesecke's UnmanagedExports.
Write a mixed mode C++/CLI DLL that consumes your C# code. The mixed mode C++/CLI is capable of export native functions using __declspec(dllexport), .def files etc.
If you chose to use UnmanagedExports, the function would look like this:
[DllExport]
public static IntPtr Authorize(string InXml)
{
// your code goes here, for now return the input value
return Marshal.StringToHGlobalAnsi(InXml);
}
Implementing the function is a little tricky because you need to return a Delphi PAnsiChar, that is a C++ char*. You cannot use string for the return type and have to use IntPtr. But how do you allocate the string so that it remains valid for the caller to use it. The code above leaks the string in an HGLOBAL.
I can't advise you definitively how to resolve the lifetime of the string. The interface you are coding to is not at all well designed. Only you with more knowledge of the interface are in a position to resolve that issue.
I know the basic premise for creating a plug ins for Unity is to create a wrapper for all the classes you want to call from within Unity. However, all of the docs and examples I have found have all expected a corresponding .cpp (if c++) or .mm (if objective-c) file.
However I'm trying to create a plug in for some native iOS code that doesn't contain any source files. All I have access to is four header files and a single .a file. Which I have gotten from here.
Now, because I don't have any .mm files to wrap I'm a bit confused as to how I can go about bringing in these files into Unity so that I can call them from within. Has anyone ever done this before?
Can someone point me to some documentation, or anything that may help me, in bringing in 4 header files and .a file into Unity as a plug in?
Please remember, there are no source files that I have access to. Only the header files themselves.
You don't need source files, even the header files are not needed as long as you know the functions' declarations.
As described in Building Plugins for iOS:
1.) Put your .a file in Assets/Plugins/iOS
2.) Look at the header files to get the function signatures you need e.g.
void RegisterUnityIPodCallbackListener (const char* gameObject, const char* method);
3.) Declare RegisterUnityIPodCallbackListener within a C# class by:
public class IPodHandler {
[DllImport("__Internal")]
private static extern void RegisterUnityIPodCallbackListener (string gameObject, string method);
public static void MyRegisterUnityIPodCallbackListener () {
if (Application.platform == RuntimePlatform.IPhonePlayer) {
RegisterUnityIPodCallbackListener (GAME_OBJECT, METHOD);
}
}
}
4.) Call at an appropriate location:
IPodHandler.MyRegisterUnityIPodCallbackListener ("MyCallbackGameObject", "MyCallbackMethod");
Common pitfalls:
You should not build directory structures within Assets/Plugins/iOS otherwise files don't get copied to the generated Xcode project
Provide a fallback solution when testing in editor player
Here is another guide: How to build Unity3d Plugin for iOS
A few notes if you get an error something like "Undefined symbols for architecture..."
1) Make sure the used architecture in .a-file matches yours (for example armv7)
2) Make sure the .a-file is compiled with libstdc++ (GNU C++ standard library) since Unity requires that.
The Estimote SDK you're are using has ObjectiveC classes. Functions in ObjectiveC can't be called directly via a Unity plugin (either can C++ classes for that matter). The reason is that function names are managled when you compile.
The interface between a Unity C# class and a library must a pure C interface. That is why there is often .mm or .cpp files along side a .a file. These are to wrap a C++ or ObjectiveC class in a pure C wrapper.
Your job is a little easier because most of the Estimote functions seem to be class functions. So you don't need to write wrapper functions to create and delete NSObjects.
Here is an example I wrote, a pure C wrapper around the TestFlightSDK. https://github.com/notoes/TestFlightUnity/blob/master/src/TestFlightCBinding.mm
Notice the extern "C" block, forcing the file the code to be compiled without name mangling. A c function signature and then an ObjectiveC call within the function.
So using the Esitmote ESTBeacon class as an example, the connectToBeacon call could like this:
extern "C" {
void ESTBeacom_Connect()
{
[ESTBeacon connectToBeacon];
}
}
And the .cs function would look like this:
class ESTBeacon {
[DllImport ("__Internal")]
private static extern void ESTBeacon_Connect();
public static void Connect() {
if( Application.platform == RuntimePlatform.IPhonePlayer )
ESTBeacon_Connect()
}
}
Put the .cs, .mm and .a files in Plugins/iOS and you'll be all good.
Use this reference to find out how to pass various data types. http://www.mono-project.com/Interop_with_Native_Libraries
I have a simple c++ Application. This Application is just printing text out.
I have also a c# .dll NET 3.5 which parses complex xml files, extracts values and saves them into a List. Its like 2 Classes with 4 methods. They open a file, parse the xml and store it into a List. When the c# .dll is done, it has a List with 10000 values;
Since i do not want to write the complex parsing XML in c++, i would like to use my c# xml parsing .dll.
Is it possible for me, to call my c# .dll from inside my c++ application, let the c# .dll parse a specified xml file, and return that created List, with the parsed xml values, to my c++ application?
In my c++ application i would proceed to modify the data within the returned list.
edit: i would be using vc++ (Microsoft Visual Studio 2010)
edit2: the vc++ app would be an expension/plug-in to another bigger Application. I would register the plug-in to that bigger application, and every time i press the icon in the menu, my vc++ application would be started
edit3: Has anyone experience with such a task? I kinda need a clear yes or no if it is possible.
edit4: i do want to avoid reading files that have been written by my .net .dll. I want my c++ app to send a string to my .net .dll and receive back a list/array object. Or is this a bad idea and i should do the xml parsing in c++ itself?
Yes, you can do it, but its kinda hard. One way to do it is to use C++ to load up CLR and execute your function, something like this:
code inspired by Blizzhackers.cc
void StartNET()
{
DWORD result;
ICLRRuntimeHost* pCLR = NULL;
CorBindToRuntimeEx(NULL, L"wks", NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pCLR);
pCLR->Start();
pCLR->ExecuteInDefaultAppDomain(L"C:\\myNET.dll", L"myNet.Program", L"Main", L"arg", &result);
pCLR->Stop();
}
This C++ code will execute the int Main(string arg) function from namespace myNet and class Program, by that I mean:
myNET.dll:
namespace myNet
{
class Program
{
int Main(string arg)
{
//and here you can run your XML parser:
List<string> myList = XMLParse();
FileStream fs = new Filestream("xmllist.txt");
StreamWriter sw = new StreamWriter(fs);
foreach(string s in myList)
sw.WriteLine(s);
sw.Close();
fs.Close();
return 1;
}
List<string> XMLParse()
{
//Your code here
return aList;
}
}
}
And after this you could use c++ to get the files from xmllist.txt, something like:
vector<char[]> getList()
{
vector<char[]> *myVector = new vector<char>;
ifstream cin("xmllist.txt");
while(!cin.eof())
{
char line[100];
cin >> line;
myVector.push(line);
}
cin.close();
return myVector;
}
I don't know if this last function works, but you get the general idea.
I created a managed/unmanaged dll in C++ some time ago. (Note though that C++.net has not the easiest syntax.)
Actually, I do not know where to start now, maybe this has the information http://channel9.msdn.com/Forums/TechOff/101918-Mixing-Managed-and-Unmanaged-C-in-a-DLL . It certainly was well possible with.. VS 2005? With that, you can have both managed an unmanaged code in one binary/assembly, and thus call the C# dll.
Apart from that, you can wrap your C# objects as COM objects. http://msdn.microsoft.com/en-us/library/ms404285.aspx . Then you can use COM interop.
In each case, marshalling the input/output would require some trial and error - it is not that obvious if you have never done it before.
Actually, this link should cover it all: http://msdn.microsoft.com/en-us/library/ms973872.aspx .
I have a console app, myapp.exe. Within the app is a function, let's call it:
public static int AddIntegers(int a, int b)
Is it possible to make this function visible externally so that a VBscript could call it? Do I have to move the function into a DLL or can I leave it in the EXE and make it visible? If so, how?
Idealistically, you should be making a DLL and set Com Visible on the functions you need to expose.
using System;
using System.Runtime.InteropServices;
namespace MyDLL
{
[ComVisible(true)]
public class Operations
{
[ComVisible(true)]
public int AddIntegers(int a, int b)
{
return a + b;
}
}
}
After you've compiled your DLL you need to register it with regasm.exe so that you can call it from VBScript:
Dim myObj
Set myObj = CreateObject("MyDLL.Operations")
Dim sum
sum = myObj.AddIntegers(3, 5)
This reply is based on the CodeProject posting How to call a .NET DLL from a VBScript by Raymund Macaalay. I recommend you read it.
Also, you should check other stackoverflow posting such as How to call C# DLL function from VBScript.
Yes, you will need to make the managed code library (DLL) visible to the VBScript (most likely through the GAC). Then in your VBScript, you can do something like:
dim yourObject = CreateObject("YourContainingObject");
yourObject.AddIntegers yourFirstInt, yourSecondInt