- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我需要与 .Net 中的 GraphicsPath.Widen()
方法相反的方法:
public GraphicsPath Widen()
Widen()
方法不接受负参数,因此我需要等效于 Inset
方法:
public GraphicsPath Inset()
您可以在开源 Inkscape 应用程序 (www.Inkscape.org) 中执行此操作,方法是转到菜单并选择“路径/插入”(插入量存储在 Inkscape 属性对话框中)。由于 Inkscape 是开源的,所以应该可以在 C#.Net 中执行此操作,但我无法终生遵循 Inkscape C++ 源代码(而且我只需要这个功能,所以我不能证明学习 C++ 是合理的)来完成这个)。
基本上,我需要一个带有此签名的 GraphicsPath 扩展方法:
public static GraphicsPath Inset(this GraphicsPath original, float amount)
{
//implementation
}
如签名所述,它将采用 GraphicsPath
对象和 .Inset()
路径传递的数量……就像 Inkscape 今天所做的那样。如果它简化了任何事情,所讨论的 GraphicsPaths 都是从 .PolyBezier
方法(而不是其他任何东西)创建的,因此除非您想要,否则无需考虑矩形、椭圆或任何其他形状这样做是为了完整性。
不幸的是,我没有使用 C++ 代码的经验,所以我几乎不可能遵循 Inkscape 中包含的 C++ 逻辑。
.
[编辑:]根据要求,这是“MakeOffset”Inkscape 代码。 Inset 的第二个参数 (double dec) 将为负数,该参数的绝对值是引入形状的量。
我知道这里有很多依赖。如果您需要查看更多 Inkscape 源文件,请在此处查看:http://sourceforge.net/projects/inkscape/files/inkscape/0.48/
int
Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Matrix *i2doc)
{
Reset (0, 0);
MakeBackData(a->_has_back_data);
bool done_something = false;
if (dec == 0)
{
_pts = a->_pts;
if (numberOfPoints() > maxPt)
{
maxPt = numberOfPoints();
if (_has_points_data) {
pData.resize(maxPt);
_point_data_initialised = false;
_bbox_up_to_date = false;
}
}
_aretes = a->_aretes;
if (numberOfEdges() > maxAr)
{
maxAr = numberOfEdges();
if (_has_edges_data)
eData.resize(maxAr);
if (_has_sweep_src_data)
swsData.resize(maxAr);
if (_has_sweep_dest_data)
swdData.resize(maxAr);
if (_has_raster_data)
swrData.resize(maxAr);
if (_has_back_data)
ebData.resize(maxAr);
}
return 0;
}
if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1 || a->type != shape_polygon)
return shape_input_err;
a->SortEdges ();
a->MakeSweepDestData (true);
a->MakeSweepSrcData (true);
for (int i = 0; i < a->numberOfEdges(); i++)
{
// int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/;
int stB = -1, enB = -1;
if (dec > 0)
{
stB = a->CycleNextAt (a->getEdge(i).st, i);
enB = a->CyclePrevAt (a->getEdge(i).en, i);
}
else
{
stB = a->CyclePrevAt (a->getEdge(i).st, i);
enB = a->CycleNextAt (a->getEdge(i).en, i);
}
Geom::Point stD, seD, enD;
double stL, seL, enL;
stD = a->getEdge(stB).dx;
seD = a->getEdge(i).dx;
enD = a->getEdge(enB).dx;
stL = sqrt (dot(stD,stD));
seL = sqrt (dot(seD,seD));
enL = sqrt (dot(enD,enD));
MiscNormalize (stD);
MiscNormalize (enD);
MiscNormalize (seD);
Geom::Point ptP;
int stNo, enNo;
ptP = a->getPoint(a->getEdge(i).st).x;
double this_dec;
if (do_profile && i2doc) {
double alpha = 1;
double x = (Geom::L2(ptP * (*i2doc) - Geom::Point(cx,cy))/radius);
if (x > 1) {
this_dec = 0;
} else if (x <= 0) {
this_dec = dec;
} else {
this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5);
}
} else {
this_dec = dec;
}
if (this_dec != 0)
done_something = true;
int usePathID=-1;
int usePieceID=0;
double useT=0.0;
if ( a->_has_back_data ) {
if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID
&& a->ebData[stB].tEn == a->ebData[i].tSt ) {
usePathID=a->ebData[i].pathID;
usePieceID=a->ebData[i].pieceID;
useT=a->ebData[i].tSt;
} else {
usePathID=a->ebData[i].pathID;
usePieceID=0;
useT=0;
}
}
if (dec > 0)
{
Path::DoRightJoin (this, this_dec, join, ptP, stD, seD, miter, stL, seL,
stNo, enNo,usePathID,usePieceID,useT);
a->swsData[i].stPt = enNo;
a->swsData[stB].enPt = stNo;
}
else
{
Path::DoLeftJoin (this, -this_dec, join, ptP, stD, seD, miter, stL, seL,
stNo, enNo,usePathID,usePieceID,useT);
a->swsData[i].stPt = enNo;
a->swsData[stB].enPt = stNo;
}
}
if (dec < 0)
{
for (int i = 0; i < numberOfEdges(); i++)
Inverse (i);
}
if ( _has_back_data ) {
for (int i = 0; i < a->numberOfEdges(); i++)
{
int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
ebData[nEd]=a->ebData[i];
}
} else {
for (int i = 0; i < a->numberOfEdges(); i++)
{
AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
}
}
a->MakeSweepSrcData (false);
a->MakeSweepDestData (false);
return (done_something? 0 : shape_nothing_to_do);
}
.
[编辑]
@Simon Mourier - 了不起的工作。代码甚至干净可读!干得好,先生。不过,我确实有几个问题要问你。
首先,Amount 的正数代表什么?我在想,对于 Offset 方法,正数是“开始”,负数是“插入”,但你的例子似乎恰恰相反。
其次,我做了一些基本测试(只是扩展了你的样本),发现了一些奇怪的地方。
这是当偏移量增加时 cool 中的“l”会发生什么(对于这样一个简单的字母,它肯定会引起问题!)。
...以及重现该代码的代码:
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath path = new GraphicsPath();
path.AddString("cool", new FontFamily("Arial"), 0, 200, new PointF(), StringFormat.GenericDefault);
GraphicsPath offset1 = path.Offset(32);
e.Graphics.DrawPath(new Pen(Color.Black, 1), path);
e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
}
最后,有点不同。这是 Wingdings 中的“S”字符(看起来像一滴泪珠):
代码如下:
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath path = new GraphicsPath();
path.AddString("S", new FontFamily("Wingdings"), 0, 200, new PointF(), StringFormat.GenericDefault);
GraphicsPath offset1 = path.Offset(20);
e.Graphics.DrawPath(new Pen(Color.Black, 1), path);
e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
}
老兄,这太近了,让我想哭。不过,它仍然不起作用。
我认为解决这个问题的方法是查看插入向量何时相交,并停止插入超过该点。如果 Inset 量太大(或路径太小)以至于什么都没有,则路径应该消失(变为空),而不是自行反转并重新扩展。
同样,我不会以任何方式批评您所做的事情,但我想知道您是否知道这些示例可能会发生什么。
(PS - 我添加了“this”关键字以使其成为扩展方法,因此您可能需要使用方法(参数)符号调用代码才能运行这些示例)
.
@RANRan 通过重新使用 GraphicsPath native 方法得出了类似的输出。伙计,这很难。他们俩都很亲密。
这是两个示例的屏幕截图,使用的是 Wingdings 中的字符“S”:
@Simon 在左边,@Ran 在右边。
这是在 Inkscape 中执行“插入”后的相同泪滴“S”字符。插图很干净:
顺便说一下,这是@Ran 测试的代码:
private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath path = new GraphicsPath();
path.AddString("S", new FontFamily("Wingdings"), 0, 200, new PointF(), StringFormat.GenericDefault);
e.Graphics.DrawPath(new Pen(Color.Black, 1), path);
GraphicsPath offset1 = path.Shrink(20);
e.Graphics.DrawPath(new Pen(Color.Red, 1), offset1);
}
最佳答案
我仍然会发布我的新解决方案,尽管它并不完美,其中包含一些需要修复的问题列表。也许您会想从中吸取一部分并改进它们,或者可能其中有一些学习值(value)。
首先是图片——我最好的嵌入泪珠符号:
我做了什么
我使用 GraphicsPath.Widen
生成给定图形的“内部”和“外部”边缘。
我扫描了生成的 GraphicsPath
的点,以移除外边缘并仅保留内边缘。
我使用 GraphicsPath.Flatten
将内边缘展平,这样图形就只包含线段(没有曲线)。
然后我扫描了内部路径上的所有点,并且对于每个当前段:
4.1。如果当前点 p 在原始路径之外,或者太靠近原始路径上的某个线段,我会在当前边上计算一个新点,该点与原始路径,我用这个点代替 p,并将它连接到我已经扫描过的部分。
4.2。解决方案中的当前限制:我从计算点继续,向前扫描。这意味着不能很好地支持带孔的形状(例如 Arial“o”)。要解决此问题,必须维护一个“断开连接”图形的列表,并重新连接在同一点结束(或彼此“足够接近”的末端)的图形。
问题
首先我会指出最主要的问题和限制,然后我会发布代码本身。
GraphicsPath.Widen
似乎无法生成干净的形状。我得到的内部图形有小的(但大部分是看不见的)“锯齿状”。这样做的意义在于 A) 我的剔除算法会产生更多噪声,B) 图中有更多点,因此性能会下降。
目前的表现勉强可以接受,如果有的话。我的解决方案目前以一种非常简单的方式(在 O(n^n) 中)进行扫描,以找到“太靠近”内边缘候选点的线段。这导致算法非常慢。它可以通过维护一些数据结构来改进,其中段按x排序,从而大大减少距离计算的次数。
我没有费心去优化代码以使用 structs
并且还有很多其他地方可以优化代码以使其更快。
不支持带孔的形状,其中内部图形必须“拆分”为多个图形(如 Arial“o”)。我知道如何实现它,但它需要更多时间:)
我会考虑采用 Simon 移动现有点以获得内部图形的方法,以及我清理该路径的方法。 (但由于 Simon 解决方案中的一个错误,我此时不能这样做,例如,导致撕裂符号的尖端移动到形状内的有效位置。我的算法认为这个位置是有效的并且不会清理它)。
代码
我无法避免想出一些我自己的数学/几何实用程序。所以这是代码...
就我个人而言,我认为这值得赏金,即使它不是一个完美的解决方案...:)
public class LineSegment
{
private readonly LineEquation line;
private RectangleF bindingRectangle;
public PointF A { get; private set; }
public PointF B { get; private set; }
public LineSegment(PointF a, PointF b)
{
A = a;
B = b;
line = new LineEquation(a, b);
bindingRectangle = new RectangleF(
Math.Min(a.X, b.X), Math.Min(a.Y, b.Y),
Math.Abs(a.X - b.X), Math.Abs(a.Y - b.Y));
}
public PointF? Intersect(LineSegment other)
{
var p = line.Intersect(other.line);
if (p == null) return null;
if (bindingRectangle.Contains(p.Value) &&
other.bindingRectangle.Contains(p.Value))
{
return p;
}
return null;
}
public float Distance(PointF p)
{
if (LineEquation.IsBetween(line.GetNormalAt(A), p, line.GetNormalAt(B)))
{
return line.Distance(p);
}
return Math.Min(Distance(A, p), Distance(B, p));
}
static float Distance(PointF p1, PointF p2)
{
var x = p1.X - p2.X;
var y = p1.Y - p2.Y;
return (float) Math.Sqrt(x*x + y*y);
}
public PointF? IntersectAtDistance(LineSegment segmentToCut, float width)
{
// always assuming other.A is the farthest end
var distance = width* (line.IsAboveOrRightOf(segmentToCut.A) ? 1 : -1);
var parallelLine = line.GetParallelLine(distance);
var p = parallelLine.Intersect(segmentToCut.line);
if (p.HasValue)
{
if (LineEquation.IsBetween(line.GetNormalAt(A), p.Value, line.GetNormalAt(B)) &&
segmentToCut.bindingRectangle.Contains(p.Value))
{
return p;
}
}
List<PointF> points = new List<PointF>();
points.AddRange(segmentToCut.line.Intersect(new CircleEquation(width, A)));
points.AddRange(segmentToCut.line.Intersect(new CircleEquation(width, B)));
return GetNearestPoint(segmentToCut.A, points);
}
public static PointF GetNearestPoint(PointF p, IEnumerable<PointF> points)
{
float minDistance = float.MaxValue;
PointF nearestPoint = p;
foreach (var point in points)
{
var d = Distance(p, point);
if (d < minDistance)
{
minDistance = d;
nearestPoint = point;
}
}
return nearestPoint;
}
}
public class LineEquation
{
private readonly float a;
private readonly float b;
private readonly bool isVertical;
private readonly float xConstForVertical;
public LineEquation(float a, float b)
{
this.a = a;
this.b = b;
isVertical = false;
}
public LineEquation(float xConstant)
{
isVertical = true;
xConstForVertical = xConstant;
}
public LineEquation(float a, PointF p)
{
this.a = a;
b = p.Y - a*p.X;
isVertical = false;
}
public LineEquation(PointF p1, PointF p2)
{
if (p1.X == p2.X)
{
isVertical = true;
xConstForVertical = p1.X;
return;
}
a = (p1.Y - p2.Y)/(p1.X - p2.X);
b = p1.Y - a * p1.X;
isVertical = false;
}
public PointF? Intersect(float x)
{
if (isVertical)
{
return null;
}
return new PointF(x, a*x + b);
}
public PointF? Intersect(LineEquation other)
{
if (isVertical && other.isVertical) return null;
if (a == other.a) return null;
if (isVertical) return other.Intersect(xConstForVertical);
if (other.isVertical) return Intersect(other.xConstForVertical);
// both have slopes and are not parallel
var x = (b - other.b) / (other.a - a);
return Intersect(x);
}
public float Distance(PointF p)
{
if (isVertical)
{
return Math.Abs(p.X - xConstForVertical);
}
var p1 = Intersect(0).Value;
var p2 = Intersect(100).Value;
var x1 = p.X - p1.X;
var y1 = p.Y - p1.Y;
var x2 = p2.X - p1.X;
var y2 = p2.Y - p1.Y;
return (float) (Math.Abs(x1*y2 - x2*y1) / Math.Sqrt(x2*x2 + y2*y2));
}
public bool IsAboveOrRightOf(PointF p)
{
return isVertical ?
xConstForVertical > p.X :
a*p.X + b > p.Y;
}
public static bool IsBetween(LineEquation l1, PointF p, LineEquation l2)
{
return l1.IsAboveOrRightOf(p) ^ l2.IsAboveOrRightOf(p);
}
public LineEquation GetParallelLine(float distance)
{
if (isVertical) return new LineEquation(xConstForVertical + distance);
var angle = Math.Atan(a);
float dy = (float) (distance/Math.Sin(angle));
return new LineEquation(a, b - dy);
}
public LineEquation GetNormalAt(PointF p)
{
if (isVertical) return new LineEquation(p.X);
var newA = -1/a;
var newB = (a + 1/a)*p.X + b;
return new LineEquation(newA, newB);
}
public PointF[] Intersect(CircleEquation circle)
{
var cx = circle.Center.X;
var cy = circle.Center.Y;
var r = circle.Radius;
if (isVertical)
{
var distance = Math.Abs(cx - xConstForVertical);
if (distance > r) return new PointF[0];
if (distance == r) return new[] {new PointF(xConstForVertical, cy) };
// two intersections
var dx = cx - xConstForVertical;
var qe = new QuadraticEquation(
1,
-2 * cy,
r * r - dx * dx);
return qe.Solve();
}
var t = b - cy;
var q = new QuadraticEquation(
1 + a*a,
2*a*t - 2*cx,
cx*cx + t*t - r*r);
var solutions = q.Solve();
for (var i = 0; i < solutions.Length; i++)
solutions[i] = Intersect(solutions[i].X).Value;
return solutions;
}
}
public class CircleEquation
{
public float Radius { get; private set; }
public PointF Center { get; private set; }
public CircleEquation(float radius, PointF center)
{
Radius = radius;
Center = center;
}
}
public class QuadraticEquation
{
public float A { get; private set; }
public float B { get; private set; }
public float C { get; private set; }
public QuadraticEquation(float a, float b, float c)
{
A = a;
B = b;
C = c;
}
public PointF Intersect(float x)
{
return new PointF(x, A*x*x + B*x + C);
}
public PointF[] Solve()
{
var d = B*B - 4*A*C;
if (d < 0) return new PointF[0];
if (d == 0)
{
var x = -B / (2*A);
return new[] { Intersect(x) };
}
var sd = Math.Sqrt(d);
var x1 = (float) ((-B - sd) / (2f*A));
var x2 = (float) ((-B + sd) / (2*A));
return new[] { Intersect(x1), Intersect(x2) };
}
}
public static class GraphicsPathExtension
{
public static GraphicsPath Shrink(this GraphicsPath originalPath, float width)
{
originalPath.CloseAllFigures();
originalPath.Flatten();
var parts = originalPath.SplitFigures();
var shrunkPaths = new List<GraphicsPath>();
foreach (var part in parts)
{
using (var widePath = new GraphicsPath(part.PathPoints, part.PathTypes))
{
// widen the figure
widePath.Widen(new Pen(Color.Black, width * 2));
// pick the inner edge
var innerEdge = widePath.SplitFigures()[1];
var fixedPath = CleanPath(innerEdge, part, width);
if (fixedPath.PointCount > 0)
shrunkPaths.Add(fixedPath);
}
}
// build the result
originalPath.Reset();
foreach (var p in shrunkPaths)
{
originalPath.AddPath(p, false);
}
return originalPath;
}
public static IList<GraphicsPath> SplitFigures(this GraphicsPath path)
{
var paths = new List<GraphicsPath>();
var position = 0;
while (position < path.PointCount)
{
var figureCount = CountNextFigure(path.PathData, position);
var points = new PointF[figureCount];
var types = new byte[figureCount];
Array.Copy(path.PathPoints, position, points, 0, figureCount);
Array.Copy(path.PathTypes, position, types, 0, figureCount);
position += figureCount;
paths.Add(new GraphicsPath(points, types));
}
return paths;
}
static int CountNextFigure(PathData data, int position)
{
var count = 0;
for (var i = position; i < data.Types.Length; i++)
{
count++;
if (0 != (data.Types[i] & (int)PathPointType.CloseSubpath))
{
return count;
}
}
return count;
}
static GraphicsPath CleanPath(GraphicsPath innerPath, GraphicsPath originalPath, float width)
{
var points = new List<PointF>();
Region originalRegion = new Region(originalPath);
// find first valid point
int firstValidPoint = 0;
IEnumerable<LineSegment> segs;
while (IsPointTooClose(
innerPath.PathPoints[firstValidPoint],
originalPath, originalRegion, width, out segs))
{
firstValidPoint++;
if (firstValidPoint == innerPath.PointCount) return new GraphicsPath();
}
var prevP = innerPath.PathPoints[firstValidPoint];
points.Add(prevP);
for (int i = 1; i < innerPath.PointCount; i++)
{
var p = innerPath.PathPoints[(firstValidPoint + i) % innerPath.PointCount];
if (!IsPointTooClose(p, originalPath, originalRegion, width, out segs))
{
prevP = p;
points.Add(p);
continue;
}
var invalidSegment = new LineSegment(prevP, p);
// found invalid point (too close or external to original figure)
IEnumerable<PointF> cutPoints =
segs.Select(seg => seg.IntersectAtDistance(invalidSegment, width).Value);
var cutPoint = LineSegment.GetNearestPoint(prevP, cutPoints);
// now add the cutPoint instead of 'p'.
points.Add(cutPoint);
prevP = cutPoint;
}
var types = new List<byte>();
for (int i = 0; i < points.Count - 1; i++)
{
types.Add(1);
}
types.Add(129);
return points.Count == 0 ?
new GraphicsPath() :
new GraphicsPath(points.ToArray(), types.ToArray());
}
static bool IsPointTooClose(
PointF p, GraphicsPath path, Region region,
float distance, out IEnumerable<LineSegment> breakingSegments)
{
if (!region.IsVisible(p))
{
breakingSegments = new LineSegment[0];
return true;
}
var segs = new List<LineSegment>();
foreach (var seg in GetSegments(path))
{
if (seg.Distance(p) < distance)
{
segs.Add(seg);
}
}
breakingSegments = segs;
return segs.Count > 0;
}
static public IEnumerable<LineSegment> GetSegments(GraphicsPath path)
{
for (var i = 0; i < path.PointCount; i++)
{
yield return
new LineSegment(path.PathPoints[i], path.PathPoints[(i + 1) % path.PointCount]);
}
}
}
关于c# - .Net 与 GraphicsPath.Widen() 相反,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4552008/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!