Unity importing DLL causes parser error? - dll

I have a DLL which I am trying to import into my Unity project. I am following this tutorial on their website example. However, this line of code causes a parser error saying that "An extern alias declaration must precede all other elements."
private static extern float FooPluginFunction ();
I have tried searching online for the solution to this error but I do not get any results that are related to Unity. I have the DLL in my assets/plugins folder. Does anyone know what is causing this error and how I would fix it?
Edit: Script containing DLL import.
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class VR : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
[DllImport ("myplugin")]
private static extern TextFunc ();
myplugin.dll is in my Unity assets/plugins folder.

This error says that you have to put your dll import above that line where you use TextFunc() and inside a class.
Edit: Check this.

Related

Trying to use C# DLL with ComVisible attribute set from unmanaged C++

TL;DR: I'm trying to use a C# library in C++. Why am I getting an undeclared identifier error when trying to use an identifier from my .tlh file? There must be tons of examples out there, but I haven't been able to find any that include both the C# and C++ code, and that work. Links to such examples would be greatly appreciated.
I have the following classes defined in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using CrystalDecisions.CrystalReports.Engine;
namespace CapsCrystalReportLib
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("B4E5F784-12E6-4311-9BB9-D5B3252F20A3")]
public interface ICapsCrystalReport
{
[DispId(1)]
void DisplayReport(string fileName);
[DispId(2)]
void PrintReport(string fileName);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("89402DE5-BA26-4AC0-AB40-00ADD2876FF4")]
[ProgId("CAPSCrystalReport.Report")]
[ComDefaultInterface(typeof(ICapsCrystalReport))]
public class CapsCrystalReport : ICapsCrystalReport
{
public void DisplayReport(string fileName)
{
MessageBox.Show("Displaying report " + fileName);
}
public void PrintReport(string fileName)
{
MessageBox.Show("Printing report " + fileName);
}
}
}
I have the following C++ program attempting to use this class:
#include "stdafx.h"
#import "W:\\CAPS Builds\\trunk\\CapsCrystalReportLib\\bin\\Debug\\CapsCrystalReportLib.tlb" no_namespace
int _tmain(int argc, _TCHAR* argv[])
{
// Initialize COM.
HRESULT hr = CoInitialize(NULL);
// Create the interface pointer.
CapsCrystalReport CRPtr(__uuidof(CapsCrystalReport));
long lResult = 0;
// Call the Add method.
CRPtr->DisplayReport("SomeReport.rpt");
// Uninitialize COM.
CoUninitialize();
return 0;
}
I am getting an undeclared identifier error. The compiler doesn't know what a CapsCrystalReport is. What am I doing wrong?
P.S. I took another look at the sample I copied this from. One of the comments asks the same question, and it was never answered.
You were very close, but CRPtr is a COM interface reference (=pointer) so it must be declared like this:
ICapsCrystalReportPtr CRPtr(__uuidof(CapsCrystalReport));
The IxxxPtr class was generated for you by #import in a .tlh file. What you can do when you have issues with #import, is just open the generated .tlh file and look at it.
Note you don't have to declare a default interface in C#, you can just declare the class like this:
[ComVisible(true)]
[Guid("89402DE5-BA26-4AC0-AB40-00ADD2876FF4")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("CAPSCrystalReport.Report")]
public class CapsCrystalReport
{
... same ...
}
And in C++, you would have to adapt your imports like this:
#import "C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\mscorlib.tlb" auto_rename
#import "W:\\CAPS Builds\\trunk\\CapsCrystalReportLib\\bin\\Debug\\CapsCrystalReportLib.tlb" no_namespace
and you would use it like that (the interface was implicitely created by .NET and wrapped by the #import):
_CapsCrystalReportPtr CRPtr(__uuidof(CapsCrystalReport));
PS: I would recommend you to keep the namespace, avoid no_namespace because it can cause problems with collisions especially in C++.

EntryPointNotFoundException occurred while calling C++ function from C#

I wish to call C++ function (here Score()) which is present in Score_Update1.dll.
Both C# & C++ files get compiled successfully. I have also put above dll into the Debug/bin of C# project. But when I run C# code it gives EntryPointNotFoundException.
What could be the reason behind this Exception?
I tried dependency walker for Score_Update1.dll. But it doesn't show any Entry Point
I wish to use PInvoke technique for calling C++ function from C#
// Score_Update1.h
#pragma once
#include <iostream>
using namespace std;
using namespace System;
extern "C"{
#define MYAPI __declspec(dllexport)
namespace Score_Update1 {
public class MYAPI UpdateScore
{
// TODO: Add your methods for this class here.
public:
void Score();
};
}
}
// This is the main Score_Updat1.dll DLL file.
#include "stdafx.h"
#include "Score_Update1.h"
using namespace Score_Update1;
void UpdateScore::Score()
{
cout<<"Score has been updated";
}
C# code is as follows:
using Score_Update1;
using System.Runtime.InteropServices;
namespace GameTesting
{
class Game
{
[DllImport("Score_Update1.dll")]
internal extern static void Score();
static void Main(string[] args)
{
try
{
Game.Score();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
The reason for EntryPointNotFoundException is that the DLL does not contain an entry point named Score. If you look at the exported names using dumpbin or some similar tool you will see mangled names.
However, using the mangled name isn't going to help you here. You've exported a class and the function you want to call is a member function. You cannot directly instantiate a C++ class from pinvoke. And you cannot call member functions. If you wish to use pinvoke you would need to flatten the class to a C style interface. Another route would be to compile the C++ code to a mixed mode C++/CLI assembly and consume that.

LNK2020 when making a variable static

I use C++/CLI to link between a .NET application and a dynamically loaded C dll.
So far all access to the DLL is instance based.
The class
namespace NxCore {
public class NativeConnector {
has variable for various references to methods:
HMODULE hLib;
NxCoreProcessTape pfNxProcessTape;
NxCorePriceToDouble pfNxPriceToDouble;
NxCoreGetDefinedString pfNxCoreGetDefinedString;
NxCoreGetSymbolAtom32 pfNxGetSymbolAtom32;
NxCoreStateGetMMQuotes pfNxStateGetMmQuotes;
I load those in a connect method:
hLib = ::LoadLibrary("NxCoreAPI.dll");
then
pfNxProcessTape = (NxCoreProcessTape)::GetProcAddress(hLib, cszNxCoreProcessTape);
pfNxPriceToDouble = (NxCorePriceToDouble)::GetProcAddress(hLib, cszNxCorePriceToDouble);
pfNxCoreGetDefinedString = (NxCoreGetDefinedString)::GetProcAddress(hLib, cszNxCoreGetDefinedString);
etc.
Now I need to move that to multi instances, so I want to load on first connect, unload on last disconnect. This means the variables must go static.
In C# I would just make them static. I try one:
static HMODULE hLib;
and linking fails:
4>NativeConnector.obj : error LNK2020: unresolved token (0A00006D) "private: static struct HINSTANCE__ * NxCore::NativeConnector::hLib" (?hLib#NativeConnector#NxCore#Connectivity#Tradex##0PAUHINSTANCE__##A)
Anyone an idea how to fix it? The header file is used on the .cpp file, so - it should not have different definitions.
Anyone can tell he how to fix that issue? As i said - I want to move the variables to be static and then use "usage counting" myself to make sure that I release on last disconnect.
From the code shown I'm not exactly clear on whether the problem occurs in a ref class (.NET class) or a native C++ class.
Here is my advice assuming a native type: You need to define the declared member
header
struct X
{
static int s_data;
};
cpp source:
#include "X.h"
int X::s_data /* = 42 */;
For ref types I'd actually expect the same semantics for static as with C#

Provide C#'s namespace from IronPython

I want to write Tomboy add-on using IronPython and I'm stuck and very beginning -- I need to provide C#'s namespace.
I mean, here's howto in writing Tomboy add-on's http://live.gnome.org/Tomboy/HowToCreateAddins
Let's start with creating the plugin
file called InsertDateTime.cs with the
following content:
using Tomboy;
namespace Tomboy.InsertDateTime
{
public class InsertDateTimeAddin : NoteAddin
{
public override void Initialize ()
{
}
public override void Shutdown ()
{
}
public override void OnNoteOpened ()
{
}
}
}
Can I do that with IronPython? Thank you.
From Python you can import the clr module and then call clr.AddReference('AssemblyName') where assembly name is a partial or full assembly name - maybe in your case it's Tomboy, it's whatever you'd compile against with C#. Then you can do "import Tomboy" or "from Tomboy import NoteAddin".
If you're hosting IronPython via the hosting APIs you can instead do scriptRuntime.LoadAssembly(typeof(NoetAddin).Assembly); so that you don't have to do it in Python. That can be particularly useful to avoid various loader context issues depending on how the assembly gets loaded.

C++ CLI Missing ';' before '}'

I am learning C++/CLI and attempting to build an Interop component for my C# project. I'm not sure what this error means or how to resolve it? Any ideas?
#pragma once
using namespace System;
namespace Firewall {
public ref class Firewall
{
void StartFirewall(){};
}
}
Unlike C#, C++ requires a semicolon after a type definition.
public ref class Firewall
{
void StartFirewall(){} // doesn't require semicolon here
}; // needs semicolon here.
In C#, you can actually have semicolons after type definitions (not recommended though) and that will be ignored. It is there for the sake of consistency with C++ syntax.
There is no need to have the ; in the place you currently have it. Instead place it after the closing } of the class Firewall.
public ref class Firewall
{
void StartFirewall(){}
};