|
Hey Navaneeth,
Let me brief you the situation. I've got a static lib file which is a win32 based and which requires application to register its display function address with the lib.
Library has few functions which keeps displaying the intermediate status of the functions called and hence the variable argument function required.
Earlier this library was used by the commandline application. Now I need to develop a GUI based application using the same lib. That is why i define variable argument function and register it with the library. This variable argument function which receives the messages from library, displays it on the Console.
Thanks a lot.
modified on Wednesday, September 9, 2009 2:01 AM
|
|
|
|
|
santoshkaif wrote: This variable argument function which receives the messages from library, displays it on the Console.
What will be the value of arguement p in your function int func1(const char *p, ...) ? Will that be some identifier to identify the types of variable arguements? If yes a possible solution is to write several method overloads that takes all possible types you are expecting. Depending on the type, you need call each overload. Also the way you implemented writing to rich text box is bad because of the reasons mentioned in my last post. Following is an improved version of your Form1 code.
public ref class Form1 : public System::Windows::Forms::Form
{
public:
static Form1^ GetInstance()
{
if(instance == nullptr)
instance = gcnew Form1();
return instance;
}
void PrintValue(System::Object value)
{
Console->AppendText(value.ToString());
}
private:
static Form1^ instance = nullptr;
System::Windows::Forms::RichTextBox^ Console;
} I have changed the Console variable to private and added a static variable named instance . This variable can be accessed using GetInstance method.
Following overloaded free functions are also added.
void WriteToScreen(int value)
{
Form1^ form = Form1::GetInstance();
form->PrintValue(value);
}
void WriteToScreen(double value)
{
Form1^ form = Form1::GetInstance();
form->PrintValue(value);
} Consider the following implementation of func1 . I am assuming in a call like func1("id", 10, 10.50) first argument will be int and second will be double.
void func1(const char* p,...)
{
va_list variable_arguements;
const char *temp;
va_start(variable_arguements, p);
int iValue;
double dValue;
for (temp = p; *temp; temp++)
{
switch (*temp)
{
case 'i':
iValue = va_arg(variable_arguements, int);
WriteToScreen(iValue);
break;
case 'd':
dValue = va_arg(variable_arguements, double);
WriteToScreen(dValue);
break;
default:
break;
}
}
va_end(variable_arguements);
} Finally, You need to modify your main method to use the singleton instance.
int main(array<System::String ^> ^args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Form1^ frm = Form1::GetInstance();
Application::Run(frm);
return 0;
} Hope that helps
|
|
|
|
|
Thanks, for a newbie this is a help to greater extent.
One more thing imp is I'm using visual studio 2005.
>> What will be the value of arguement p in your function int func1(const char *p, ...)?
Value of argument p in function int func1(const char *p, ...) can be anything. Its as good as printf(). I've built the sample library and application project and is as below
library.h
--------------------
#ifndef _LIBRARY_H_
#define _LIBRARY_H_
void register_func(int(*pConsoleHandle)(const char* p, ...));
void library_message1(void);
void library_message2(void);
void library_message3(void);
void library_operation(void);
#endif //_LIBRARY_H_
library.c
-----------------------
#include"library.h"
int(*pFuncHandle)(const char* p, ...);
void register_func(int(*pConsoleHandle)(const char* p, ...))
{
pFuncHandle = pConsoleHandle;
}
void library_message1(void)
{
pFuncHandle("Library msg1 is up!!");
}
void library_message2(void)
{
char msg[] = "Library msg2";
pFuncHandle("Library is up!!");
}
void library_message3(void)
{
int i = 3;
pFuncHandle("Library msg%d is up!!",i);
}
void library_operation(void)
{
library_message1();
library_message2();
library_message3();
}
this code generates library.lib which is to be included in GUI application.
GUI_Application:
-----------------------
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include "library.h"
namespace GUI_APP {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
int DisplayMessage(const char* msg, ...);
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
register_func(DisplayMessage);
}
protected:
~Form1()
{
if (components)
{
delete components;
}
}
public: static System::Windows::Forms::RichTextBox^ Console;
protected:
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->Console = (gcnew System::Windows::Forms::RichTextBox());
this->SuspendLayout();
this->Console->Location = System::Drawing::Point(-2, -2);
this->Console->Name = L"richTextBox1";
this->Console->Size = System::Drawing::Size(296, 265);
this->Console->TabIndex = 0;
this->Console->Text = L"";
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 262);
this->Controls->Add(this->Console);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
}
#pragma endregion
void library_func(void)
{
library_operation();
}
};
int DisplayMessage(const char* msg, ...)
{
int ret = 0;
va_list ap;
char *pBuffer = new char[256];
va_start(ap, msg);
ret = vsprintf(pBuffer, msg, ap);
GUI_APP::Form1::Console->AppendText(gcnew System::String((const char*)msg));
delete(pBuffer);
va_end(ap);
return (ret);
}
}
This GUI_application is where i'm unable to call and use unmanaged functions.
Thanks in advance
modified on Wednesday, September 9, 2009 2:52 PM
|
|
|
|
|
Well in that case we can make use of std::stringstream and have only one overload. You need to modify the PrintValue method in your form to take a managed string rather than System::Object .
void PrintValue(String^ value)
{
Console->AppendText(value);
} WriteToScreen method now requires only one overload which takes a std::stringstream& .
void WriteToScreen(std::stringstream& value)
{
std::string str = stream.str();
String^ managedString = gcnew String(str.c_str());
Form1^ form = Form1::GetInstance();
form->PrintValue(managedString);
} func1 is also modified to behave like printf .
void func1(const char* p,...)
{
const char *temp; int iValue; double dValue; bool percentageFound = false;
va_list variable_arguements;
va_start(variable_arguements, p);
std::stringstream stream;
for (temp = p; *temp; temp++)
{
if(*temp != '%' && !percentageFound)
stream << *temp;
else if(!percentageFound)
{
percentageFound = true;
continue;
}
if(percentageFound)
{
switch (*temp)
{
case 'd':
iValue = va_arg(variable_arguements, int);
stream << iValue;
break;
default:
break;
}
percentageFound = false;
}
}
va_end(variable_arguements);
WriteToScreen(stream);
} I have added only for %d and you can add cases for all other types. A function call like func1("Twelve = %d and Ten = %d",12,10); will print Twelve = 12 and Ten = 10 .
Hope this helps.
|
|
|
|
|
But i get compilation errors as
error C2065: 'stream' : undeclared identifier
error C2228: left of '.str' must have class/struct/union type is ''unknown-type''
Error occurs at
void WriteToScreen(std::stringstream& value){
std::string str = stream.str(); <---------------------Error
String^ managedString = gcnew String(str.c_str());
Form1^ form = Form1::GetInstance();
form->PrintValue(managedString);
}
Just for compilation purpose, if i make the following modification
std::string str;
I start getting following linker errors
Compiling managed resources...
Read in 0 resources from "f:\Projects\Temp\MTK3\GUI\GUI_APP\GUI_APP\GUI_APP\Form1.resx"
Writing resource file... Done.
Compiling resources...
Linking...
Form1.obj : error LNK2028: unresolved token (0A00001F) "void __clrcall register_func(int (__clrcall*)(char const *,...))" (?register_func@@$$FYMXP6MHPBDZZ@Z) referenced in function "public: __clrcall GUI_APP::Form1::Form1(void)" (??0Form1@GUI_APP@@$$FQ$AAM@XZ)
GUI_APP.obj : error LNK2028: unresolved token (0A000016) "void __clrcall library_operation(void)" (?library_operation@@$$FYMXXZ) referenced in function "private: void __clrcall GUI_APP::Form1::library_func(void)" (?library_func@Form1@GUI_APP@@$$FA$AAMXXZ)
Form1.obj : error LNK2028: unresolved token (0A000022) "void __clrcall library_operation(void)" (?library_operation@@$$FYMXXZ) referenced in function "private: void __clrcall GUI_APP::Form1::library_func(void)" (?library_func@Form1@GUI_APP@@$$FA$AAMXXZ)
Form1.obj : error LNK2019: unresolved external symbol "void __clrcall library_operation(void)" (?library_operation@@$$FYMXXZ) referenced in function "private: void __clrcall GUI_APP::Form1::library_func(void)" (?library_func@Form1@GUI_APP@@$$FA$AAMXXZ)
GUI_APP.obj : error LNK2001: unresolved external symbol "void __clrcall library_operation(void)" (?library_operation@@$$FYMXXZ)
Form1.obj : error LNK2019: unresolved external symbol "void __clrcall register_func(int (__clrcall*)(char const *,...))" (?register_func@@$$FYMXP6MHPBDZZ@Z) referenced in function "public: __clrcall GUI_APP::Form1::Form1(void)" (??0Form1@GUI_APP@@$$FQ$AAM@XZ)
fatal error LNK1120: 5 unresolved externals
GUI_APP - 7 error(s), 1 warning(s)
|
|
|
|
|
Common language runtime support is set to /clr:pure.
To call the library functions "register_func" or "library_operation" from the static library.lib, if
Common language runtime support is set to (/clr) then the errors thrown are
error C3269: 'GUI_APP::Form1::DisplayMessage' : a member-function of a managed type cannot be declared with '...'
Form1.cpp
error C3269: 'GUI_APP::Form1::DisplayMessage' : a member-function of a managed type cannot be declared with '...'
error C3269: 'GUI_APP::Form1::DisplayMessage' : a member-function of a managed type cannot be declared with '...'
error C3821: 'GUI_APP::Form1::WriteToScreen': managed type or function cannot be used in an unmanaged function
error C3642: 'void GUI_APP::Form1::WriteToScreen(std::stringstream &)' : cannot call a function with __clrcall calling convention from native code
error C3175: 'GUI_APP::Form1::WriteToScreen' : cannot call a method of a managed type from unmanaged function 'GUI_APP::Form1::DisplayMessage'
note: 'int GUI_APP::Form1::DisplayMessage(const char *,...)': to compile this varargs function as managed code, use /clr:pure
Form1.h(76) : see declaration of 'GUI_APP::Form1::DisplayMessage'
warning C4793: 'vararg' : causes native code generation for function 'int GUI_APP::Form1::DisplayMessage(const char *,...)'
Form1.h(76) : see declaration of 'GUI_APP::Form1::DisplayMessage'
error C3645: 'GUI_APP::Form1::DisplayMessage' : __clrcall cannot be used on functions compiled to native code
GUI_APP - 7 error(s), 1 warning(s)
|
|
|
|
|
The code which I provided compiles fine on my machine. Have you included proper header files? Have you used proper namespaces? Also use /clr compiler switch rather than /clr:pure .
|
|
|
|
|
Yeah, Common language runtime support is set to "clr" only.
Enclosing code just in case to verify if am doing anything wrong
#pragma once
#include <iostream>
#include <stdio.h>
#include <stdarg.h>
#include <sstream>
#include <iostream>
#include <string>
#pragma managed(push, off)
extern "C"{
#include "library.h"
};
#pragma managed(pop)
namespace GUI_APP {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace std;
int DisplayMessage(const char* p,...);
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
register_func(DisplayMessage);
}
static Form1^ GetInstance()
{
if(instance == nullptr)
instance = gcnew Form1();
return instance;
}
void PrintValue(String^ value)
{
Console->AppendText(value);
}
private:
static Form1^ instance = nullptr;
System::Windows::Forms::RichTextBox^ Console;
protected:
~Form1()
{
if (components)
{
delete components;
}
}
protected:
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->Console = (gcnew System::Windows::Forms::RichTextBox());
this->SuspendLayout();
this->Console->Location = System::Drawing::Point(-2, -2);
this->Console->Name = L"richTextBox1";
this->Console->Size = System::Drawing::Size(296, 265);
this->Console->TabIndex = 0;
this->Console->Text = L"";
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 262);
this->Controls->Add(this->Console);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);
}
#pragma endregion
void library_func(void)
{
library_operation();
}
void WriteToScreen(std::stringstream& value)
{
std::string str = stream.str();
String^ managedString = gcnew String(str.c_str());
Form1^ form = Form1::GetInstance();
form->PrintValue(managedString);
}
};
int DisplayMessage(const char* p,...)
{
const char *temp; int iValue; double dValue; bool percentageFound = false;
va_list variable_arguements;
va_start(variable_arguements, p);
int DisplayedCharCount = 0;
std::stringstream stream;
for (temp = p; *temp; temp++)
{
DisplayedCharCount++;
if(*temp != '%' && !percentageFound)
stream << *temp;
else if(!percentageFound)
{
percentageFound = true;
continue;
}
if(percentageFound)
{
switch (*temp)
{
case 'd':
iValue = va_arg(variable_arguements, int);
stream << iValue;
break;
default:
break;
}
percentageFound = false;
}
}
va_end(variable_arguements);
WriteToScreen(stream);
return DisplayedCharCount;
}
}
following are the error messages
error C2065: 'stream' : undeclared identifier
error C2228: left of '.str' must have class/struct/union
type is ''unknown-type''
error C3861: 'WriteToScreen': identifier not found
warning C4793: 'vararg' : causes native code generation for function 'int GUI_APP::DisplayMessage(const char *,...)'
see declaration of 'GUI_APP::DisplayMessage'
pls let me know where i am going wrong?
if i make "DisplayMessage" as member function of "Form1" class, then below error is thrown
'GUI_APP::Form1::DisplayMessage' : a member-function of a managed type cannot be declared with '...'
modified on Thursday, September 10, 2009 1:57 PM
|
|
|
|
|
WriteToScreen should be a free-function not a member of Form1 . Take that function from class and put it on top of DisplayMessage .
|
|
|
|
|
Hey Navaneeth, Now it works. Tons of Thanks to u, u've done wonders for me!!
|
|
|
|
|
I need your expert advice again.
This is in continuation with the earlier code. If "DisplayMessage" function is registered with library function and if one of the lib functions(which would have lots of display messages) is called from this application, console(i.e. richtextbox) gives the impression to the user that its hanged. Once the control is returned back to application(from the lib function), all the messages get displayed on console at once.
I want to know how to get the lib messages displayed on console as and when lib func does it, instead of displaying all the messages at once(which also gives the impression to the user its hung).
|
|
|
|
|
In such case, use a separate thread to handle the messages. To access rich text box from worker thread, you need to use Invoke /BeginInvoke to avoid cross-thread exceptions. This[^] post may help you.
|
|
|
|
|
I use this sort of code in a program i'm making at the moment:
if (loginForm == nullptr) {
loginForm = gcnew Login;
loginForm->Show();
} else {
loginForm->Activate();
}
I'm wondering how do i get the Login form to call methods from the initial (parent) form?
I include the login form in this form and set loginForm to nullptr when the form runs. The second form loads, but i can't work out how to call a method from the parent. Any ideas?
|
|
|
|
|
rtshield wrote: I'm wondering how do i get the Login form to call methods from the initial (parent) form?
You can make the methods public and when login form is instantiated, pass the parent forms instance to login form via constructor.
if (loginForm == nullptr) {
loginForm = gcnew Login(this);
loginForm->Show();
} else {
loginForm->Activate();
} Login forms constructor should also be modified to accept a parent forms object.
ref class ParentForm;
ref class LoginForm : public Form
{
private:
ParentForm^ parentForm = nullptr;
public:
LoginForm(ParentForm^ p)
: parentForm(p)
{
}
} You need to forward declare parent form in the header file and include parentform.h in your CPP file to avoid circular dependencies.
|
|
|
|
|
Hi,
I have a function to display 3 values to the user by writing them to 3 labels. Basically there is some intensive data processing going on in the background by native C++ code. every now and then the data processing calculates these three numbers and signals an Event Object. A function in the mnaged form class waits for this Event to be set, and when that happens it will write these 3 numbers, and also plot some data.
Here is the function:
private: void updateNoise(void){
double temp = global->_noise_value[0];
this->noiseLabel1->Text = L"Coil 1 Noise:" + temp.ToString();
temp = global->_noise_value[1];
this->noiseLabel2->Text = L"Coil 2 Noise:" + temp.ToString();
temp = global->_noise_value[2];
this->noiseLabel3->Text = L"Coil 3 Noise:" + temp.ToString();
}
I know this code works because if I call it in a simple event like a button-click without the data processing running it will correctly write doubles to the labels, but when it is called in the middle of my program, well in the debugger the first line copies a value correctly, but the function returns when it executes the second line.
Here is the code for waiting for an event:
int rc = WaitForSingleObject(global->_startPlotEvent, 1000);
switch (rc){
case WAIT_OBJECT_0:
for (int i=0; i<3; i++)
this->drawPlot(i);
this->updateNoise();
break;
case WAIT_TIMEOUT:
break;
default:
assert(0);
}
Also I know this method works because plotting works fine everytime as long as updateNoise is not called before drawPlot.
So any idea what is behind this problem? I am new to .NET and C++/CLI but it makes no sense why this wouldn't work.
|
|
|
|
|
alzaeem wrote: Also I know this method works because plotting works fine everytime as long as updateNoise is not called before drawPlot.
In the code you have given, updateNoise is not called before drawPlot .
alzaeem wrote: well in the debugger the first line copies a value correctly, but the function returns when it executes the second line.
That is weird. Do you mean it returns when executing the line temp = global->_noise_value[1]; ? What is the type of _noise_value ? Is that a managed array? Have you inspected the values in this array? Is updateNoise executed on the main thread?
A wild guess assuming your application is multi-threaded: _noise_value is available for all threads in execution and you are reading it without using any synchronization mechanisms. So there may be chances for data to be overwritten by the worker thread in between you read the values. Try to apply locking when reading and writing values to the _noise_value variable. Or avoid using global variables. Modify the methods to take changed values as arguments and when calling these methods, pass the changed values.
|
|
|
|
|
N a v a n e e t h wrote: In the code you have given, updateNoise is not called before drawPlot.
I meant that if drawPlot is called before updateNoise, then plotting works fine but still no updating of noise labels; but if updateNoise is called first, then neither works.
N a v a n e e t h wrote: That is weird. Do you mean it returns when executing the line temp = global->_noise_value[1];? What is the type of _noise_value? Is that a managed array? Have you inspected the values in this array? Is updateNoise executed on the main thread?
No it returns when it executes the first line that is supposed to change the text on the label.
noise_value is a c array declared on the stack. When debugging, temp gets a valid double value form _noise_value[0]. These values tend to be very small, around e-10, but I am guessing ToString shouldn't have a problem with that.
_noise_value is available to multiple threads, and there is no explicit synchronization mechanism for its access, but what happens is that a thread calculates noise values, writes them to a file and then sets the Event for the other thread to update the Labels; there is no risk of the noise values changing before the labels are updated because noise is only calculated around once every 10 seconds. Anyway even if the noise values change, from what I know that should only result in writing the wrong values to the labels.
|
|
|
|
|
Hi,
Controls (such as Labels) should only be touched by the thread that created them, which most often is the main thread. You may want to read this[^] and research InvokeRequired.
|
|
|
|
|
Objective: Modify a dll(binary) to either
1. Call another exe
2. Call another dll (function)
3. Modify the Dll binary by inserting code(Asm/Binary) and generate a shell(cmd.exe)
I know it sounds stupid but I hope you guys got the idea. Please feel free if you need more clarification...I have been trying to do this but no info is available. Now Im wondering is it even possible?
Dll injection/hooking/tampering...any(all) concept is ok, just want to know whats the roadblock to achieve something like this.
Eg:
I have a 3rd part dll called Game.dll. now I want to modify it somehow/anyhow and make it call calc.exe....alrite you guys can laugh !!!!
|
|
|
|
|
Repost: please read the guidelines on posting to these forums and post your question once only.
|
|
|
|
|
I have a data glove, its driver is visual c++ version. I want to code a test program in managed C++ has some trouble.
===========================================================
// fglove.h
//
typedef struct
{
// The contents of this struct are platform-dependent and subject to
// change. You should not manipulate the contents of this struct directly.
void *m_pStuff;
} fdGlove;
fdGlove *fdOpen(char *pPort);
===========================================================
//FrmDataGlove.h
#pragma once
#include < stdio.h >
#include < stdlib.h >
#include < vcclr.h >
#include "fglove.h"
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Runtime::InteropServices;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::IO::Ports;
public ref class FrmDataGlove : public System::Windows::Forms::Form
{
public: fdGlove *m_pGlove;
private: System::Void btnGetData_Click(System::Object^ sender, System::EventArgs^ e)
{
char* p1;
p1=StringToPChar(this->serialPort->PortName);
m_pGlove=fdOpen(p1); //maybe there has wrong syntax
}
}
Above is I capture some code in my project, when I compile the compiler has the wrong message:
--------------------------------------------------------------------------------------------
錯誤 1 error LNK2028: 無法解析的語彙基元 (0A000010) "struct fdGlove * __clrcall fdOpen(char *)" (?fdOpen@@$$FYMPAUfdGlove@@PAD@Z) 在函式 "private: void __clrcall DataGlove::FrmDataGlove::btnGetData_Click(class System::Object ^,class System::EventArgs ^)" (?btnGetData_Click@FrmDataGlove@DataGlove@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) 中被參考 DataGlove.obj
-------------------------------------------------------------------------------------------
錯誤 2 error LNK2019: 無法解析的外部符號 "struct fdGlove * __clrcall fdOpen(char *)" (?fdOpen@@$$FYMPAUfdGlove@@PAD@Z) 在函式 "private: void __clrcall DataGlove::FrmDataGlove::btnGetData_Click(class System::Object ^,class System::EventArgs ^)" (?btnGetData_Click@FrmDataGlove@DataGlove@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) 中被參考 DataGlove.obj
-------------------------------------------------------------------------------------------
錯誤 3 fatal error LNK1120: 2 個無法解析的外部符號 C:\Documents and Settings\jimhuang688\My Documents\Visual Studio 2005\Projects\DataGlove\Debug\DataGlove.exe
-------------------------------------------------------------------------------------------
|
|
|
|
|
jetjeankimo wrote: when I compile the compiler has the wrong message:
These are linker errors.
How fdGlove struct is compiled (compiler switch used)? From the __clrcall in the error message, I am guessing you are using /clr:pure switch to compile managed code.
Possible reason for this error will be in the mismatch of calling conventions. You native code will be using the normal __cdecl and the managed code compiled with /clr:pure will be using __clrcall . To resolve, try to use the same calling convention for both. I believe, you need /clr switch.
|
|
|
|
|
Thanks for your suggestion.
My compiler setting in common language runtime support that has /clr, /clr:pure, /clr:safe and /clr:oldSyntax. I choose the /clr.
C/C++ advanced setting has _cdel(/Gd), _fastcal(/Gr) and /stdcall(/Gz). I choose the _cdecl(/Gd).
After compile, it has these errors.
--------------------------------------------------------------------------------------------------
錯誤 1 error LNK2028: 無法解析的語彙基元 (0A000010) "struct fdGlove * __cdecl fdOpen(char *)" (?fdOpen@@$$FYAPAUfdGlove@@PAD@Z) 在函式 "private: void __clrcall DataGlove::FrmDataGlove::btnGetData_Click(class System::Object ^,class System::EventArgs ^)" (?btnGetData_Click@FrmDataGlove@DataGlove@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) 中被參考 DataGlove.obj
-----------------------------------------------------------------------------------------------------
錯誤 2 error LNK2019: 無法解析的外部符號 "struct fdGlove * __cdecl fdOpen(char *)" (?fdOpen@@$$FYAPAUfdGlove@@PAD@Z) 在函式 "private: void __clrcall DataGlove::FrmDataGlove::btnGetData_Click(class System::Object ^,class System::EventArgs ^)" (?btnGetData_Click@FrmDataGlove@DataGlove@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) 中被參考 DataGlove.obj
------------------------------------------------------------------------------------------------------
錯誤 3 fatal error LNK1120: 2 個無法解析的外部符號 C:\Documents and Settings\jimhuang688\My Documents\Visual Studio 2005\Projects\DataGlove\Debug\DataGlove.exe
---------------------------------------------------------------------------------------------------------
|
|
|
|
|
Is your native struct and managed code in same project? If both are different projects, what type of project is the native one? Is common language runtime support is enabled there?
|
|
|
|
|
My project is CLR Windows Form Application project,and just use one project. The /clr setting is enabled. Thank you!
|
|
|
|
|